I have been creating a small app using react.js. I take 'performance' into account excessively.
So I have a simple child component named "Spinner". My goal is to make sure this component never re-renders.
Here is my component:
import React, {PureComponent} from 'react';
export default class Spinner extends PureComponent {
render() {
return (
<div className="spinner">
<div className="bounce1"></div>
<div className="bounce2"></div>
<div className="bounce3"></div>
</div>
)
}
}
In the time of the re-rendering with 'react-addons-perf', the component is always rendering, I am using PureComponent because I want that component to render only one time, I read that I can use immutable props but I don't know how to make this possible.
If I make some like to this:
componentDidMount() {
this.renderState = false;
}
shouldComponentUpdate(nextProps, nextState) {
return (this.renderState === undefined) ? true : this.renderState;
}
It is rendering only one time, but I believe that there is a better way.
How do I avoid the re-render? or maybe How I can make a immutable props?
You don't need an extra logic for componentShouldUpdate, since you don't want your component to rerender ever.
Adding only this should be enough to prevent component to rerender:
shouldComponentUpdate(nextProps, nextState) {
return false
}
For stateless components that don't need props, we can use a combination of a Functional (stateless) component, and babel's React constant elements transformer to optimize the component creation, and prevent rerenders entirely.
Add React constant elements transformer to your build system. According to the docs the transformer will:
Hoists element creation to the top level for subtrees that are fully
static, which reduces call to React.createElement and the resulting
allocations. More importantly, it tells React that the subtree hasn’t
changed so React can completely skip it when reconciling.
Change the spinner to a stateless component.
const Spinner = () => (
<div className="spinner">
<div className="bounce1"></div>
<div className="bounce2"></div>
<div className="bounce3"></div>
</div>
);
export default Spinner;
You can make your props immutable in React by using Immutable JS to transform your array props into Lists and object props int Maps. With this library you can use simple checks to check the equality of arrays/objects (instead of going through keys/values for equality):
shouldComponentUpdate(nextProps) => {
this.props.complexObjectAsMap === nextProps.complexObjectAsMap
}
But since your component doesn't have any props - this doesn't look the right question. In your case I'd go with Ori Drori answer.
Related
Learning React and Redux. I'm playing with the Redux examples, and currently looking at the todo-with-undo example (don't think its possible to set up a sandbox or something). In this setup there is a container component (TodoList) and it's children (Todo).
I modified the Todo from a functional component to PureComponent class so that shouldComponentUpdate() returns false if all the prop references are the same, and thus the components shouldn't update (but they will still re-render???).
Adding code to log when a child updates with componentDidUpdate() method and also to log when re-rendering shows that every time a new Todo is added to the container, all elements update and rerender - even whilst being PureComponents - it should be the case that shallow comparisons of old and new props for each child should return false for the new or updated child.
Being an example built by Redux I doubt that they update the store incorrectly (not in an immutable fashion), as that is the point of their concept, so I believe I am not fully understanding something -> someone please help...
Because the <TodoList> is passing a new callback function reference to each child:
export default class TodoList extends Component {
render() {
return (
<ul>
{this.props.todos.map((todo, index) =>
<Todo {...todo}
key={index}
onClick={() => this.props.onTodoClick(index)} />
)}
</ul>
);
}
}
That will always cause the child to re-render, even if it's attempting to optimize renders based on props comparisons.
PureComponent does not mean it will not update, it just mean React will handle comparison of props and state for you by implementing shouldComponentUpdate with shallow prop and state comparison.
I am learning ReactJS and I've learned that there are UI Components and Container Components. The Container Components are implemented using classes extending React.Component and contain state and good old render method, whereas the UI Components are created using functions and they are concerned with UI only as they only take the data from props.
Sample stateless functional components:
const Ninjas = (props) => {
const { ninjas } = props;
const ninjalist = ninjas.map((x) => {
var divStyle = {
color: getRandomColor(),
};
return (
<div className="ninja" key={x.key} style={divStyle}>
<p>Name: {x.name}</p>
<p>Age: {x.age}</p>
<p>Belt: {x.belt}</p>
</div>
);
});
return <div className="ninja-list">{ninjalist}</div>;
};
export default Ninjas;
The same sample as a Container Component
export default class Ninjas extends Component {
getRandomColor = () => {
....
return color;
};
render() {
const { ninjas } = this.props;
const ninjalist = ninjas.map((x) => {
var divStyle = {
color: this.getRandomColor(),
};
return (
<div className="ninja" key={x.key} style={divStyle}>
<p>Name: {x.name}</p>
<p>Age: {x.age}</p>
<p>Belt: {x.belt}</p>
</div>
);
});
return <div className="ninja-list">{ninjalist}</div>;
}
}
So my question is why do we even bother to make a UI component (not using the render method which is used in Container Component) when we could have easily done the same thing as a Container Component.
Functional state-less components (what wrongly you refer as UI Components, all components are UI components both statefull and stateless) are simply a short-hand method to create components that simply render something based on props passed and do not need to keep internal state.
Of course one can always use class-based components which extend React.Component. But why not have a short-hand to save time and space and simplify things if we can. There is nothing forcing you to create functional components, you can always use class-based components, only if you need to simplify and save time and space.
According to Functional vs Class-Components in React article:
So why should I use functional components at all?
You might ask yourself why you should use functional components at
all, if they remove so many nice features. But there are some benefits
you get by using functional components in React:
Functional component are much easier to read and test because they are plain JavaScript functions without state or lifecycle-hooks
You end up with less code
They help you to use best practices. It will get easier to separate container and presentational components because you need to think more
about your component’s state if you don’t have access to setState() in
your component
The React team mentioned that there may be a performance boost for functional component in future React versions
I would add a 5th point that React references (with React 16.3+) which provide functionality to access the DOM nodes directly cannot be used with Functional Components.
In React v.16.8+ useState hooks are introduced which enable functional components to be state-full while still being functional.
Furthermore with the introduction of React.memo higher-order component we can use memoization to avoid re-rendering of a functional component given that it renders same stuff for same props (shallow tested for difference)
right now im have tree component like this
<UserOrderApproval>
<Table>
<TableRow>
<ComponentList />
</ChildrenProps1>
</Parent>
</UserOrderApproval>
im take props from redux in UserOrderApproval component, and passing that props to every children component. The problem, when children component make some change in redux, the state from UserOrderApproval component will change & make all children component re render & make component life cycle run again. How to do prevent this?
How best practice to passing props from parent to nested children like this?
Many Thanks
As KuchBhi said, you'll need to use the shouldComponentUpdate lifecycle method.
shouldComponentUpdate is called any time when new props or state are passed to the component and by default returns true (might only return true for updated props, not 100% sure). The method accepts two parameters: nextProps and nextState. You can then compare these to this.props and this.state to decide whether you should update or not.
The default/typical implementation of this method is something along the lines of this (pseudo):
shouldComponentUpdate(nextProps, nextState) {
//Really it's a deeper equality check, not just the props/state object
return this.props !== nextProps || this.state !== nextState;
}
What you can do as an alternative is build this out a bit more with cases where false is returned. Here is an example from one of my projects where I only want to rerender when two specific props are different:
shouldComponentUpdate(nextProps) {
const minUpdated = this.props.min !== nextProps.min;
const maxUpdated = this.props.max !== nextProps.max;
return minUpdated || maxUpdated;
}
The component also has the props such as scale, align, width, etc. but I don't want to update when I receive those as new props so I don't check to see if they're not equal.
You could essentially just return false in this method and never update after the initial load, but I would avoid that as it defeats the purpose of react.
edit: As varoons said, this is likely a great scenario for you to use the new context API and I highly recommend looking into it, but it is useful to know about component lifecycle methods as well.
Use shouldComponentUpdate(), pure components, or connect redux to only the child components that need them.
https://reactjs.org/docs/react-component.html#shouldcomponentupdate
https://reactjs.org/docs/react-api.html#reactpurecomponent
This is a good scenario to use React's context api as this seems like a prop drilling case - You are passing data down to components that do not use it.
You could make UserOrderApproval(assuming it is the parent connected to the global state/redux) the context provider and ComponentList the consumer. This way only the components handling/using the data will re-render.
https://reactjs.org/docs/context.html
https://scotch.io/tutorials/get-to-know-reacts-new-context-api
Total React noob here. I have two sibling Components in my React application. I want to display a Loading message in Component A when a certain method is executed in Component B
I'm familiar with passing state from a parent to child in React, but how can a sibling be notified to display it's loader?
Here's what I have so far
export default class ComponentA extends Component {
constructor(props) {
super(props);
this.state = {};
}
render(){
return(
{/* Loader */}
{ this.state.loading === true &&
<div className="loader"></div>
}
)
}
}
export default class ComponentB extends Component {
// Constructor, bindings and stuff...
getData(){
// Update Component A's "loading" state here.
// Once the data is fetched, set "loading" to false
}
render(){
return(
<div>
<button onClick="this.getData"></button>
<table>
<tbody>
{/* ... */}
</tbody>
</table>
</div>
)
}
}
Setting up both Components to inherit state from a Parent Component doesn't seem desirable because I'll have many siblings with nested Components that I'll also want to trigger this loader
Any input is appreciated!
In React, data flows from the top, down. You'd need to wrap Component A and B in a parent and keep the state in the parent as a single point of truth.
However, as you have said after a while this can become tedious when dealing with components several levels deep. You don't want to have to keep passing the state down.
I'd suggest looking into Redux (the docs are excellent) as well as the container(smart)/component(dumb) architecture.
In addition to the links above, I'd really suggest taking the time to watch this free tutorial series from Redux's creator, Dan Abramov.
Hope that helps!
First of all, you said that Component A is a child component of Component B but I don't see any relationship between the two components. But you can do one of 2 things in my opinion. One is to import Component A into Component B as a child component and pass the data to Component A as props (easy). Second way requires you to understand redux. In this case, I don't see the necessity due to the size of the app. However, basically you can have a mastermind at the top of the React component tree to pass down the state to any component. So updating the store by dispatching the new data from Component B will enable Component A to have an access to the data. Redux would be great from large applications and for data that needs to be distributed in multiple places.
Dan Abramov says
...a component is pure if it is guaranteed to return the same result given the same props and state.
So if a component is supplied with the same props the same output will always be returned. This is clear.
He then says
pure components... don’t rely on deep mutations in props or
state, so their rendering performance can be optimized by a shallow
comparison in their shouldComponentUpdate() hook
But this means I could supply a pure component with the same props object, but with a difference located deeper inside said props object, and the component would render the same but for different (albeit a deep difference) props. This means this constraint is not enforced.
Is declaring a component as extends PureComponent really saying to ReactJS "I know what I am doing. I guarantee I am using immutable state. So you need only perform shallow props comparisons in shouldComponentUpdate"?
Finally, PureComponents provide a shallow shouldComponentUpdate method by default - presumably this can be overridden with whatever you want (even a deep comparison)?
Is declaring a component as extends PureComponent really saying to
ReactJS "I know what I am doing. I guarantee I am using immutable
state. So you need only perform shallow props comparisons in
shouldComponentUpdate"?
Yes
Finally, PureComponents provide a shallow shouldComponentUpdate method
by default - presumably this can be overridden with whatever you want
(even a deep comparison)?
You can override it. React will try to warn you not to do so. In this case its better to inherit from Component instead.
https://medium.com/groww-engineering/stateless-component-vs-pure-component-d2af88a1200b
class Welcome extends React.PureComponent {
render() {
return <h1>Welcome</h1>
}
}
Hello = () => {
return <h1>Hello</h1>;
}
So above there is an example of a very simple Welcome Pure Component
and Hello Stateless Component. When you use these two in your Parent
Component, you will see Hello will re-render whenever Parent Component
will re-render but Welcome Component will not
Also in cases where you want to use lifecycle methods of Component
then we have to use Pure Components as stateless components don't have
lifecycle methods.
Please read about Pure Render Checks
https://github.com/vasanthk/react-bits/blob/master/gotchas/01.pure-render-checks.md
and good articles there :
https://flexport.engineering/optimizing-react-rendering-part-1-9634469dca02
https://flexport.engineering/optimizing-react-rendering-part-2-7b2e9a9ea21f
https://flexport.engineering/ending-the-debate-on-inline-functions-in-react-8c03fabd144