Suppose I have 10k of record and whenever I am trying to update state using setState every time component is re-render but I want after all changes on state component should render once only.
example :-
constructor(){
this.state={
employeeList:[{name:a},{name:b},{name:c},{name:d},{name:e}.....]
}
}
I want to update a,b,c,d,e to 1 ,2 ,3 ,4,5 by using this.setState() but after update all value i need to re-render component not after update one by one.
Please help me.
There are two possible ways to do this:
Use the 'shouldComponentUpdate' and decide in it whether to render.
Use a pure component.
Using 'shouldComponentUpdate'
The following text is copied from "How does React decide to re-render a component?":
"By default, shouldComponentUpdate returns true. That’s what causes a component to render everytime there is a state change. However, you can overwrite shouldComponentUpdate to give it more “smarts” if you need the performance boost. Instead of letting React re-render all the time, you can tell React when you don’t want to trigger a re-render."
Use a pure component
The following text is copied from "Why and How to Use PureComponent in React.js": "PureComponent changes the life-cycle method shouldComponentUpdate and adds some logic to automatically check whether a re-render is required for the component. This allows a PureComponent to call method render only if it detects changes in state or props."
You need to handle your state updates differently
Instead of updating state separately for each value, you would update it once like
update() {
const newValues = [1,2,3,4,5];
const newEmployeeList = this.state.employeeList.map((obj, index) => {
return {...obj, name: newValues[index]};
})
this.setState({employeeList: newEmployeeList})
}
Related
In my application I have a page change mechanism that uses one of the properties of parent component state.
So I do something like:
class mainComponent{
state={
mypage:null
}
onclickhandler(page){
this.setState({mypage:page});
}
render(){
return <div>{page}</div>
};
}
In my "page" property I have various input fields and other components.
When I change the page, all inputs get updated with new values. However, my custom nested components are never re-created.
Instead, reach just calls componentDidUpdate on them.
Is there a way to force it to construct a new nested component somehow?
React won't recreate component when it's not needed - it's a part of optimizations and general way react works.
When 'new', 'expected' component exists (the same type, the same or no key id) it only receives updated props.
Updating props sometimes doesn't force rerendering (it's guaranteed for state updates). PureComponent compares props shallowly, you can check shouldComponentUpdate (should return true to force render).
I started to learn ReactJS I would like to know what are the scenario to use componentWillReceiveProps? what is the purpose for using it?
Currently i'm using props without it, is there any impact ?
In cases where you want to take action in child component in response to props change, componentWillReceiveProps was supposed to the right candidate. Example of it is when you have a user component which calls and API to fetch the user details based on an ID that is provided by its parent and anytime the prop ID changes, you would want to trigger the API call again and re-render the updated view.
However, componentWillReceiveProps is called on every parent re-render and not just prop change, so while you are using it, you must provide a conditional check between previous and currentProps like
componentWillReceiveProps(nextProps) {
if(nextProps.id !== this.props.id) {
//API call goes here
}
}
However from v16 onwards, its discouraged to use componentWillReceiveProps and instead its usage is split into componentDidUpdate which is where you can make API calls and getDerivedStateFromProps or memoized functions or key updates in order to make state change based on prop change.
Please check componentWillReceiveProps vs getDerivedStateFromProps for more details
If your component accept some props and if on change of that props you would like to do some business logic or state change, componentWillReceiveProps is the lifecycle method where this logic should go, as every time props changes componentWillReceiveProps is called.
I am using react+redux. I have 100000(example) ImageComponent inside a parent component let's say, ImageGrid. Functionality on every ImageComponent is, user can like, delete and select.
The problem is, when I like, delete or select any single ImageComponent, I update it's state in redux and upon every single state change, it renders the whole 100000 ImageComponent.
How to avoid this unnecessary re-rendering of those ImageComponent which has not changed?
You can add shouldComponentUpdate to the ImageComponent to prevent it from re-rendering if its props/state has not changed.
If your props are shallow, you can declare it as React.PureComponent. If ImageComponent is connected to Redux, then this is automatically done (no re-rendering if mapStateToProps return the same props).
You probably shouldn't be rendering 10000 components at once though. Try react-virtualized.
Also you should provide a unique and stable key for each component.
shouldComponentUpdate() can be used to prevent the default rendering problem
Official doc: https://reactjs.org/docs/react-component.html#shouldcomponentupdate
Here is a post about this similar problem
I am setting multiple states in setState, but one of the states will not always change though. Is React smart enough to bypass setting that state it remains unchanged?
No, by default React will update your component with every setState call.
You can use shouldComponentUpdate to let the component know that it shouldn't update when certain conditions are met.
shouldComponentUpdate(nextProps, nextState) {
// If these match, we know we don't need a redraw
if (this.state.foo === nextState.foo) return false;
// Otherwise, continue with the update
return true;
}
Note that shouldComponentUpdate doesn't affect child-components, who will each check their own update conditions when they receive new props or new state.
You can read more about the React component lifecycle over here.
I haven't been able to find a clear answer to this, hope this isn't repetitive.
I am using React + Redux for a simple chat app. The app is comprised of an InputBar, MessageList, and Container component. The Container (as you might imagine) wraps the other two components and is connected to the store. The state of my messages, as well as current message (the message the user is currently typing) is held in the Redux store. Simplified structure:
class ContainerComponent extends Component {
...
render() {
return (
<div id="message-container">
<MessageList
messages={this.props.messages}
/>
<InputBar
currentMessage={this.props.currentMessage}
updateMessage={this.props.updateMessage}
onSubmit={this.props.addMessage}
/>
</div>
);
}
}
The issue I'm having occurs when updating the current message. Updating the current message triggers an action that updates the store, which updates the props passing through container and back to the InputBar component.
This works, however a side effect is that my MessageList component is getting re-rendered every time this happens. MessageList does not receive the current message and doesn't have any reason to update. This is a big issue because once the MessageList becomes big, the app becomes noticeably slower every time current message updates.
I've tried setting and updating the current message state directly within the InputBar component (so completely ignoring the Redux architecture) and that "fixes" the problem, however I would like to stick with Redux design pattern if possible.
My questions are:
If a parent component is updated, does React always update all the direct children within that component?
What is the right approach here?
If a parent component is updated, does React always update all the direct children within that component?
No. React will only re-render a component if shouldComponentUpdate() returns true. By default, that method always returns true to avoid any subtle bugs for newcomers (and as William B pointed out, the DOM won't actually update unless something changed, lowering the impact).
To prevent your sub-component from re-rendering unnecessarily, you need to implement the shouldComponentUpdate method in such a way that it only returns true when the data has actually changed. If this.props.messages is always the same array, it could be as simple as this:
shouldComponentUpdate(nextProps) {
return (this.props.messages !== nextProps.messages);
}
You may also want to do some sort of deep comparison or comparison of the message IDs or something, it depends on your requirements.
EDIT: After a few years many people are using functional components. If that's the case for you then you'll want to check out React.memo. By default functional components will re-render every time just like the default behavior of class components. To modify that behavior you can use React.memo() and optionally provide an areEqual() function.
If a parent component is updated, does React always update all the direct children within that component?
-> Yes , by default if parent changes all its direct children are re-rendered but that re-render doesn't necessarily changes the actual DOM , thats how React works , only visible changes are updated to real DOM.
What is the right approach here?
-> To prevent even re-rendering of virtual DOM so to boost your performance further you can follow any of the following techniques:
Apply ShouldComponentUpdate Lifecycle method - This is applied only if your child component is class based , you need to check the current props value with the prev props value ,and if they are true simply return false.
Use Pure Component -> This is just a shorter version to above method , again works with class based components
Use React memo -> this is the best way to prevent Rerendering even if you have functional components ,you simply need to wrap your components export with React.memo like : export default React.memo(MessageList)
Hope that helps!
If parent component props have changed it will re-render all of its children which are made using React.Component statement.
Try making your <MessageList> component a React.PureComponent to evade this.
According to React docs: In the future React may treat shouldComponentUpdate() as a hint rather than a strict directive, and returning false may still result in a re-rendering of the component. check this link for more info
Hope this helps anyone who is looking for the right way to fix this.
If you're using map to render child components and using a unique key on them (something like uuid()), maybe switch back to using the i from the map as key. It might solve the re-rendering issue.
Not sure about this approach, but sometimes it fixes the issue