React – Anti-patterns to be avoided

Initializing the state using properties

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: props.count
    };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState({
      count: this.state.count + 1
    });
  }

  render() {
    return (
      <div>
        {this.state.count}
        <button onClick={this.handleClick}>+</button>
      </div>
    );
  }
}

Issues

We have a duplicated source of truth because “Props” and “State” hold a similar value. It’s unclear which is the current and trustworthy value to use inside the component, and to display to the user.
If the count property passes to the component changes, the state does not get updated.

Solution

Change name of state into “initialCount”, prop has the name of “count”

constructor(props) {
  super(props);
  
  this.state = {
    count: props.initialCount
  };

  this.handleClick = this.handleClick.bind(this);
}

If we use it like so, it is clear that the parent only has a way to initialize the counter, but any future values of the initialCount property will be ignored.

Mutating the state

handleClick() {
  this.state.count++;
}
handleClick() {
  this.state.items.push('baz');
  this.setState({
    items: this.state.items
  });
}

render() {
  return (
    <div>
      {this.state.items.length}
      <button onClick={this.handleClick}>+</button>
    </div>
  );
}

Issues

If we mutate the state without using setState, two bad things can happen:

  • The state changes without making the component re-render
  • Whenever setState gets called in the future, the mutated state gets applied

Solution

Fix it by using the setState API

handleClick() {
  this.setState({
    items: this.state.items.concat('baz')
  });
}

Using indexes as a key

Issues

In a list, the item index always starts from 0, even if we push a new item to the TOP, React still think we changed the values of the existing items (0, 1, 2 for instance), and added a new element at index 3.
So, our new 0th item will be displayed with old 0th item, new 1th item will be displayed with old 1th item, and so on.

Solution

The key has to be unique and stable, identifying one, and only one, item

Spreading properties on DOM elements

<Component {...props} />

Issues

When we spread properties into a DOM element, we run the risk of adding unknown HTML attributes, which is bad practice.

Solution

Create a property called “domProps” that we can spread safely to the component because we are explicitly saying that it contains valid DOM properties.

const Spread = props => <div {...props.domProps} />;
...
<Spread foo="bar" domProps={{ className: 'baz' }} />

Be the first to comment

Leave a Reply

Your email address will not be published.


*