The Parent (MyList
in my example) component renders an array thru a Child (MyComponent
) component. Parent decides to change properties in the array, what is React way of triggering child re-rendering?
All I came up with is this.setState({});
in Parent after tweaking the data. Is this a hack or a React way of triggering an update?
JS Fiddle: https://jsfiddle.net/69z2wepo/7601/
var items = [ {id: 1, highlighted: false, text: "item1"}, {id: 2, highlighted: true, text: "item2"}, {id: 3, highlighted: false, text: "item3"}, ]; var MyComponent = React.createClass({ render: function() { return <div className={this.props.highlighted ? 'light-it-up' : ''}>{this.props.text}</div>; } }); var MyList = React.createClass({ toggleHighlight: function() { this.props.items.forEach(function(v){ v.highlighted = !v.highlighted; }); // Children must re-render // IS THIS CORRECT? this.setState({}); }, render: function() { return <div> <button onClick={this.toggleHighlight}>Toggle highlight</button> {this.props.items.map(function(item) { return <MyComponent key={item.id} text={item.text} highlighted={item.highlighted}/>; })} </div>; } }); React.render(<MyList items={items}/>, document.getElementById('container'));
Simply use forceUpdate method to force React to Re-Render the component.
Forcing an update on a React class component In any user or system event, you can call the method this. forceUpdate() , which will cause render() to be called on the component, skipping shouldComponentUpdate() , and thus, forcing React to re-evaluate the Virtual DOM and DOM state.
This doesn't only mean the component's render function will be called, but also that all its subsequent child components will re-render, regardless of whether their props have changed or not.
memo() If you're using a React class component you can use the shouldComponentUpdate method or a React. PureComponent class extension to prevent a component from re-rendering.
The problem here is that you're storing state in this.props
instead of this.state
. Since this component is mutating items
, items
is state and should be stored in this.state
. (Here's a good article on props vs. state.) This solves your rendering problem, because when you update items
you'll call setState
, which will automatically trigger a re-render.
Here's what your component would look like using state instead of props:
var MyList = React.createClass({ getInitialState: function() { return { items: this.props.initialItems }; }, toggleHighlight: function() { var newItems = this.state.items.map(function (item) { item.highlighted = !item.highlighted; return item; }); this.setState({ items: newItems }); }, render: function() { return ( <div> <button onClick={this.toggleHighlight}>Toggle highlight</button> { this.state.items.map(function(item) { return <MyComponent key={item.id} text={item.text} highlighted={item.highlighted}/>; }) } </div> ); } }); React.render( <MyList initialItems={initialItems}/>, document.getElementById('container') );
Note that I renamed the items
prop to initialItems
, because it makes it clear that MyList
will mutate it. This is recommended by the documentation.
You can see the updated fiddle here: https://jsfiddle.net/kxrf5329/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With