Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find unused style definitions in React?

Is there a way to automagically find unused style definitions in a React based project, like in this example?

Before:

const styles = StyleSheet.create({
  name: {
    color: '#e5e5e5'
  }
});

const Hello = React.createClass({
  render: function() {
    return <Text style={styles.name}>Hello {this.props.name}</Text>;
  }
});

After:

Developer has changed styles and "name" is not required any more. How can this kind of dead style code be automatically found?

const styles = StyleSheet.create({
  name: { // Redundant now!
    color: '#e5e5e5'
  },
  foo: {
    color: '#e2e3b5'
  }
});

const Hello = React.createClass({
  render: function() {
    return <Text style={styles.foo}>Hello {this.props.name}</Text>;
  }
});
like image 508
Timo Ernst Avatar asked Mar 22 '17 15:03

Timo Ernst


1 Answers

Possible solution

1) helpers.js

// helpers.js
import ReactTestUtils from 'react-addons-test-utils'

export function unusedStyles(component, styles) {
    const renderer = ReactTestUtils.createRenderer();
    renderer.render(component);
    const rendered = renderer.getRenderOutput();
    const myStylesInUse = stylesInUse(rendered);
    return filterStyles(styles, myStylesInUse);
}

function stylesInUse(el) {
    var arr = [];

    function go(el) {
        const { children, style } = el.props;
        const childrenType = Object.prototype.toString.call(children);
        style && arr.push(style)
        if(childrenType === '[object Object]') {
            go(children);
        } else if(childrenType === '[object Array]') {
            children.forEach(child => { go(child) });
        }
    }

    go(el);

    return arr;
}

function filterStyles(styles, compStyles) {
    const arr = [];

    for(let key in styles) {
        const found = compStyles.find(item => item === styles[key]);
        if(!found) arr.push(key)
    }

    return arr;
}

2) Component.js

import { unusedStyles } from './helpers';

const styles = StyleSheet.create({
  one: {
    color: 'one'
  },
  two: {
    color: 'two'
  },
  three: {
    color: 'three'
  }
});

class Hello extends Component {

  render() {
    return (
      <div style={styles.one}>
        <div style={style.two}>Hello!</div>
      </div>
    )
  }

}

// here you can test your styles
const myUnusedStyles = unusedStyles(<Hello />, styles)
// => ['three']

if(myUnusedStyles.length) {
  console.log('UNUSED STYLES DETECTED', myUnusedStyles);
}

export default Hello
like image 188
disstruct Avatar answered Oct 27 '22 09:10

disstruct