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' }} />
Leave a Reply