In a React class module, If counts of rendering in PureComponent are same as ones of it in Component, which one should I use? PureComponent is always faster, better than Component?
render(){
//console.log('rendered');
return(<div>...
}
Without measuring, it is hard to say.
PureComponent is nothing fancy, it justs handles shouldComponentUpdate method automatically for you.
shouldComponentUpdate(nextProps, nextState) {
return stuffChanged(this, nextProps, nextState))
}
Let's say stuffChanged is a function which does heavy computation and thus takes considerable amount of time too.
So now react will spend time in running this function (diffing) and then also in updating the DOM.
Whereas, if you did not have shouldComponentUpdate method, then your component will not have to spend time in running stuffChanged expensive function.
It will update the DOM if diffing and reconciliation of react tells it to.
So, if you just have a Component there is one diff i.e updating the DOM.
But if you have a PureComponent there is atleast one diff and sometimes two i.e diffing for state and props and then updating the DOM.
Which means PureComponent is going to be slower usually but faster occasionally.
Unless you have measured your performance of the app with some profiling tool, I would suggest you to just stick to Component.
If you wrap use PureComponent everywhere without measuring, chances are you would end up slowing your web app.
If said component doesn't have many changing parts (ie, different state or props) then pure component is a simplified way of making sure it doesn't re-render needlessly. Otherwise, use componenetDidUpdate would be a more in-depth way to handle those
Related
After spending some time learning React I understand the difference between the two main paradigms of creating components.
My question is when should I use which one and why? What are the benefits/tradeoffs of one over the other?
ES6 classes:
import React, { Component } from 'react';
export class MyComponent extends Component {
render() {
return (
<div></div>
);
}
}
Functional:
const MyComponent = (props) => {
return (
<div></div>
);
}
I’m thinking functional whenever there is no state to be manipulated by that component, but is that it?
I’m guessing if I use any life cycle methods, it might be best to go with a class based component.
New Answer: Much of the below was true, until the introduction of React Hooks.
componentDidUpdate can be replicated with useEffect(fn), where fn is the function to run upon rerendering.
componentDidMount methods can be replicated with useEffect(fn, []), where fn is the function to run upon rerendering, and [] is an array of objects for which the component will rerender, if and only if at least one has changed value since the previous render. As there are none, useEffect() runs once, on first mount.
state can be replicated with useState(), whose return value can be destructured to a reference of the state and a function that can set the state (i.e., const [state, setState] = useState(initState)). An example might explain this more clearly:
const Counter = () => {
const [count, setCount] = useState(0)
const increment = () => {
setCount(count + 1);
}
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>+</button>
</div>
)
}
default export Counter
As a small aside, I have heard a number of people discussing not using functional components for the performance reasons, specifically that
"Event handling functions are redefined per render in functional components"
Whilst true, please consider if your components are really rendering at such a speed or volume that this would be worth concern.
If they are, you can prevent redefining functions using useCallback and useMemo hooks. However, bear in mind that this may make your code (microscopically) worse in performance.
But honestly, I have never heard of redefining functions being a bottleneck in React apps. Premature optimisations are the root of all evil - worry about this when it's a problem.
Old Answer: You have the right idea. Go with functional if your component doesn't do much more than take in some props and render. You can think of these as pure functions because they will always render and behave the same, given the same props. Also, they don't care about lifecycle methods or have their own internal state.
Because they're lightweight, writing these simple components as functional components is pretty standard.
If your components need more functionality, like keeping state, use classes instead.
More info: https://facebook.github.io/react/docs/reusable-components.html#es6-classes
UPDATE Jan 2023
TLDR; Functions are the best way to create components. React.Component is a legacy API.
"We recommend to define components as functions instead of classes."
"Class components are still supported by React, but we don’t recommend using them in new code."
https://beta.reactjs.org/reference/react/Component
UPDATE March 2019
Building on what was stated in my original answer:
Are there any fundamental differences between React functions and
classes at all? Of course, there are — in the mental model.
https://overreacted.io/how-are-function-components-different-from-classes/
UPDATE Feb 2019:
With the introduction of React hooks, it seems as though the React teams wants us to use functional components whenever possible (which better follows JavaScript's functional nature).
Their motivation:
It’s hard to reuse stateful logic between components.
Complex components become hard to understand.
Classes confuse both people and machines.
A functional component with hooks can do almost everything a class component can do, without any of the draw backs mentions above.
I recommend using them as soon as you are able.
Original Answer
Functional components aren't any more lightweight than class based components, "they perform exactly as classes." - https://github.com/facebook/react/issues/5677#issuecomment-241190513
The above link is a little dated, but React 16.7.0's documentation says
that functional and class components:
are equivalent from React’s point of view
https://reactjs.org/docs/components-and-props.html#stateless-functions
There is essentially no difference between a functional component and a class component that just implements the render method, other than the syntax.
In the future (quoting the above link):
we [React] might add such optimizations
If you're trying to boost performance by eliminating unnecessary renders, both approaches provide support. memo for functional components and PureComponent for classes.
https://reactjs.org/docs/react-api.html#reactmemo
https://reactjs.org/docs/react-api.html#reactpurecomponent
It's really up to you. If you want less boilerplate, go functional. If you love functional programming and don't like classes, go functional. If you want consistency between all components in your codebase, go with classes. If you're tired of refactoring from functional to class based components when you need something like state, go with classes.
Always try to use stateless functions (functional components) whenever possible. There are scenarios where you'll need to use a regular React class:
The component needs to maintain state
The component is re-rendering too much and you need to control that via shouldComponentUpdate
You need a container component
UPDATE
There's now a React class called PureComponent that you can extend (instead of Component) which implements its own shouldComponentUpdate that takes care of shallow props comparison for you. Read more
As of React 17 the term Stateless Functional components is misleading and should be avoided (React.SFC deprecated, Dan Abramov on React.SFC), they can have a state, they can have hooks (that act as the lifecycle methods) as well, they more or less overlap with class components
Class based components
state
lifecycle methods
memoization with React.PureComponent
Functional components:
state (useState, useReducer hooks)
lifecycle methods (via the useEffect, useLayoutEffect hooks)
memoization via the memo HOC
Why i prefer Funtional components
React provide the useEffect hook which is a very clear and concise way to combine the componentDidMount, componentDidUpdate and componentWillUnmount lifecycle methods
With hooks you can extract logic that can be easily shared across components and testable
less confusion about the scoping
React motivation on why using hooks (i.e. functional components).
I have used functional components for heavily used application which is in production. There is only one time I used class components for "Error Boundaries" because there is no alternative "Error Boundaries" in functional components.
I used "class component" literally only one time.
Forms are easier with functional, because you can reuse form input fields and you can break them apart with React display conditionals.
Classes are one big component that can't be broken down or reused. They are better for function-heavy components, like a component that performs an algorithm in a pop-up module or something.
Best practice is reusability with functional components and then use small functional components to assemble complete sections, ex.- form input fields imported into a file for a React form.
Another best practice is to not nest components in the process of doing this.
Class-based components offer a more structured and organized way to define and implement a component, and they provide additional features and capabilities, such as the ability to use local state and lifecycle methods. This can make them a good choice for creating complex components that require a lot of logic and functionality.
On the other hand, functional components are simpler and easier to work with, and they can be more performant because they are more lightweight. They are also easier to test and debug, because they are pure functions that don't have side effects. This makes them a good choice for creating simple components that don't require a lot of logic or state management.
I want to understand what we lose if we don't store the data in state. We can still trigger re-render by using this.setState({}). Please provide in-depth analysis.
Note that I am not concerned to maintain the state of application(usually done via Redux, Mobx etc.)
class App extends React.Component {
constructor() {
super();
// this.state = { counter: 0 };//Am I loosing something by not doing in this way
}
counter = 0;
increment() {
this.counter++;
this.setState({});//trigger re-render as new object is set to state
// this.state.counter++;
// this.setState(this.state);
}
render() {
return (
<div>
<h2>Click button to increment counter</h2>
<button type="button" onClick={()=>this.increment()}>{this.counter}</button>
</div>
);
}
}
//export default App;
ReactDOM.render(
<App />,
document.body
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
One of the biggest things you'd lose are lifecycle methods and maintainability. The whole idea behind React's state is to make it easier to keep data in sync both in that component and in any child components being passed data from that state, but for all that to work as intended, you need to update the state using this.setState() and read from it through this.state.
What React does when calling this.setState() (besides updating the state) is go through the necessary lifecycle steps as well. One of the main things it does then is re-render the component (and it's children), but as you said, you can trigger that using this.setState({}) which to some extent is true, but only if you're also okay with losing:
Performance
JavaScript is fast. React is fast. What do you get when you cross fast with fast? I don't know, but it's probably something really fast. Especially if you like using React's PureComponent, which is exactly the same as Component with the difference that PureComponent implements shouldComponentUpdate using shallow state and props comparison, whereas Component doesn't. What this means is that if you don't update anything (state and props both stay the same), the PureComponent won't re-render the component, whereas Component will. If you don't use React's state system, you can't really use PureComponent for better performance, nor can you implement shouldComponentUpdate, since you can't compare your old data with your new data. You'd have to re-implement that performance feature yourself.
Stability
Saying goodbye to React's state system in favor of a hacky solution also means saying goodbye to application stability, and saying hello to more problems down the road than you can count. Let's take the performance problems from the above point, and let's put them to scale. In order for you to have a more performant application, you'd have to either repeat the above for the whole application, or create a generic solution that you could re-use across components. Not to mention the fact that remembering to call this.setState({}) every time you update the data, just to make the component re-render. Forget it once, and your application will start to display inconsistent data, because even though "your state" updated, React's state hasn't. Scale that up, and you've got a problem.
Colleagues that don't want to hurt you
Let's face it. You're probably either new to programming, new to React, or haven't worked in a team, and that's okay, we all start from somewhere. What's really important, though, is not making your team want to hurt you so bad you'd have to pick a new specialty. One that doesn't require fingers and/or eyes.
The benefit of using tried and tested frameworks, as well as using them correctly, is that there's less hassle for everybody. Nobody has to create and maintain hacky solutions to already existing use cases. Nobody has to tear their hair out due to inconsistent rendering. Nobody has to lose an eye or break any fingers because somebody thought it'd be a good idea to reinvent the wheel, but this time as a cube.
TL;DR & Final words
Don't reinvent the wheel. It already exists, and it's round
Work smart, not hard
Either use React's built-in state system or Redux/MobX (see 1.)
Use this.setState for updating, this.state for reading. Don't directly mutate state, as React won't call any lifecycle methods, resulting in unexpected behavior and bugs
Setting component state on a component instance can lead to buggy component and have an impact on maintability of the component.
Correctness of Component state isn't guaranteed
If you generate clicks faster than this.counter is incremented, the computed counter isn't guaranteed to be correct.
setState guarantees that multiple calls to it are batched together to be applied.
For this reason, counter value is guaranteed.
this.setState(prevState => ({counter: prevState.counter + 1}))
No separation of rendering logic from state mutation
Also, in use cases where you have to avoid a render when the component state didn't change, React.Component lifecycle methods like shouldComponentUpdate captures the next state _effectively separating the decision to render from update to state.
Keeping state on the component instance will have you computing the next state, comparing it to the previous one and deciding whether to force a rerender.
This can become difficult to maintain if you have more state to manage for the component.
One specific thing I can think of is that state and props are big things in react.
For instance, when you call .setState it isn't exactly a trigger to update ui but rather a queued update request.
Why does it matter?
Several reasons (and more here):
A setState doesn't necessarily mean that the component will indeed re-render. if the state is left the same as before, react will notice, and will skip the render cycle which gives you a performance boost (and is one of the key advantages on top of the virtual DOM).
setState is async (usually), and several setState can happen before a single render. thus, setState({a:true});setState({a:false}); can in theory just skip the intermediate render (performance boost again).
One other thing is the idea that there is only one source of truth to a react component.
This is a design principal that allows easier development and debugging as it helps with code readability. React is just a View framework (as in MVC / MV*, just without the M). It is up to you to do the rest. Since it is just a View, Components are essentially just HTML (or rather, JSX) representation (or bindings, depending on lexicon) of plain data.
That data is state, and therefor has a special status.
It makes it much easier to think of (and code) React, with the understanding the Components are just (state) => { <html>} functions. when you want to see where the state changes, you just look for setState. as simple as that. you could of course store other things as class members, but that would defeat the purpose of simplicity and readability.
*PS: the above also means that time-travel is easy. you just play the state changes backwards (in theory) which is also a cool benefit of keeping things simple.
React says pure render can optimize performance.
And now React has PureComponent.
Should I use React.PureComponent everywhere?
Or when to use React.PureComponent and where is the most proper postion to use React.PureComponent?
Not always. You should use it when a component could re-render even if it had the same props and state. An example of this is when a parent component had to re-render but the child component props and state didn't change. The child component could benefit from PureComponent because it really didn't need to re-render.
You shouldn't necessarily use it everywhere. It doesn't make sense for every component to implement the shallow shouldComponentUpdate(). In many cases it adds the extra lifecycle method without getting you any wins.
It can drastically save you rendering time if you have many cases where root level components update while the children do not need to do so. That being said, you will gain much more from using PureComponent in your root level nodes (i.e. PureComponent will not improve overall performance as much in leaf level components because it only saves renders from that component).
Some caveats to PureComponent are explained very well in the react docs.
React.PureComponent's shouldComponentUpdate() only shallowly compares the objects.
You could accidentally miss rendering updates if your prop changes are deep in a nested object. PureComponent is only great with simple flat objects/props or by using something like ImmutableJS to detect changes in any object with a simple comparison.
Furthermore, React.PureComponent's shouldComponentUpdate() skips prop updates for the whole component subtree. Make sure all the children components are also "pure".
PureComponent only works whenever the rendering of your component depends only on props and state. This should always be the case in react but there are some examples where you need to re-render outside of the normal react lifecycle. In order for PureComponent to work as expected (skipping the re-rendering you don't really need to happen), every descendant of your PureComponent should be 'pure' (dependent only upon props and state).
According to this reference, no (you should not use it everywhere):
(I work on React.) [...] If we recommended that PureComponent be used everywhere, it would probably be the default already. Rather -- the comparison to decide whether or not a component should be rerendered costs something, and in the case that you do want to rerender, all of the time spent checking whether you should have rerendered is wasted.
Instead, we'd suggest you be conscious of where you need to do the comparisons. It's usually only in a couple of places in your app. Good candidates are on the children of a long list or around large parts of the app that change independently (that is, cases where you know the parent should often rerender but the child shouldn't). A few well-placed shouldComponentUpdate (or PureComponent) uses can go a long way.
--
I found a tweet from Dan Abramov saying the same thing (30 Jul 2016).
Came to know that from React v15.3.0, we have a new base class called PureComponent to extend with PureRenderMixin built-in. What I understand is that, under the hood this employs a shallow comparison of props inside shouldComponentUpdate.
Now we have 3 ways to define a React component:
Functional stateless component which doesn't extend any class
A component that extends PureComponent class
A normal component that extends Component class
Some time back we used to call stateless components as Pure Components, or even Dumb Components. Seems like the whole definition of the word "pure" has now changed in React.
Although I understand basic differences between these three, I am still not sure when to choose what. Also what are the performance impacts and trade-offs of each?
Update:
These are the question I expect to get clarified:
Should I choose to define my simple components as functional (for the sake of simplicity) or extend PureComponent class (for performance sake)?
Is the performance boost that I get a real trade-off for the
simplicity I lost?
Would I ever need to extend the normal Component class when I can always use PureComponent for better performance?
How do you decide, how do you choose between these three based on the purpose/size/props/behaviour of our components?
Extending from React.PureComponent or from React.Component with a custom shouldComponentUpdate method have performance implications. Using stateless functional components is an "architectural" choice and doesn't have any performance benefits out of the box (yet).
For simple, presentational-only components that need to be easily reused, prefer stateless functional components. This way you're sure they are decoupled from the actual app logic, that they are dead-easy to test and that they don't have unexpected side effects. The exception is if for some reason you have a lot of them or if you really need to optimise their render method (as you can't define shouldComponentUpdate for a stateless functional component).
Extend PureComponent if you know your output depends on simple props/state ("simple" meaning no nested data structures, as PureComponent performs a shallow compare) AND you need/can get some performance improvements.
Extend Component and implement your own shouldComponentUpdate if you need some performance gains by performing custom comparison logic between next/current props and state. For example, you can quickly perform a deep comparison using lodash#isEqual:
class MyComponent extends Component {
shouldComponentUpdate (nextProps, nextState) {
return !_.isEqual(this.props, nextProps) || !_.isEqual(this.state, nextState);
}
}
Also, implementing your own shouldComponentUpdate or extending from PureComponent are optimizations, and as usual you should start looking into that only if you have performance issues (avoid premature optimizations).
As a rule of thumb, I always try to do these optimisations after the application is in a working state, with most of the features already implemented. It's a lot easier to focus on performance problems when they actually get in the way.
More details
Functional stateless components:
These are defined just using a function. Since there's no internal state for a stateless component, the output (what's rendered) only depends on the props given as input to this function.
Pros:
Simplest possible way of defining a component in React. If you don't need to manage any state, why bother with classes and inheritance? One of the main differences between a function and a class is that with the function you are sure the output depends only on the input (not on any history of the previous executions).
Ideally in your app you should aim to have as many stateless components as possible, because that normally means you moved your logic outside of the view layer and moved it to something like redux, which means you can test your real logic without having to render anything (much easier to test, more reusable, etc.).
Cons:
No lifecycle methods. You don't have a way to define componentDidMount and other friends. Normally you do that within a parent component higher in the hierarchy so you can turn all the children into stateless ones.
No way to manually control when a re-render is needed, since you can't define shouldComponentUpdate. A re-render happens every time the component receives new props (no way to shallow compare, etc.). In the future, React could automatically optimise stateless components, for now there's some libraries you can use. Since stateless components are just functions, basically it's the classic problem of "function memoization".
Refs are not supported: https://github.com/facebook/react/issues/4936
A component that extends PureComponent class VS A normal component that extends Component class:
React used to have a PureRenderMixin you could attach to a class defined using React.createClass syntax. The mixin would simply define a shouldComponentUpdate performing a shallow comparison between the next props and the next state to check if anything there changed. If nothing changes, then there's no need to perform a re-render.
If you want to use the ES6 syntax, you can't use mixins. So for convenience React introduced a PureComponent class you can inherit from instead of using Component. PureComponent just implements shouldComponentUpdate in the same way of the PureRendererMixin. It's mostly a convenience thing so you don't have to implement it yourself, as a shallow comparison between current/next state and props is probably the most common scenario that can give you some quick performance wins.
Example:
class UserAvatar extends Component {
render() {
return <div><img src={this.props.imageUrl} /> {{ this.props.username }} </div>
}
}
As you can see the output depends on props.imageUrl and props.username. If in a parent component you render <UserAvatar username="fabio" imageUrl="http://foo.com/fabio.jpg" /> with the same props, React would call render every time, even if the output would be exactly the same. Remember though that React implements dom diffing, so the DOM would not be actually updated. Still, performing the dom diffing can be expensive, so in this scenario it would be a waste.
If the UserAvatar component extends PureComponent instead, a shallow compare is performed. And because props and nextProps are the same, render will not be called at all.
Notes on the definition of "pure" in React:
In general, a "pure function" is a function that evaluates always to the same result given the same input. The output (for React, that's what is returned by the render method) doesn't depend on any history/state and it doesn't have any side-effects (operations that change the "world" outside of the function).
In React, stateless components are not necessarily pure components according to the definition above if you call "stateless" a component that never calls this.setState and that doesn't use this.state.
In fact, in a PureComponent, you can still perform side-effects during lifecycle methods. For example you could send an ajax request inside componentDidMount or you could perform some DOM calculation to dynamically adjust the height of a div within render.
The "Dumb components" definition has a more "practical" meaning (at least in my understanding): a dumb component "gets told" what to do by a parent component via props, and doesn't know how to do things but uses props callbacks instead.
Example of a "smart" AvatarComponent:
class AvatarComponent extends Component {
expandAvatar () {
this.setState({ loading: true });
sendAjaxRequest(...).then(() => {
this.setState({ loading: false });
});
}
render () {
<div onClick={this.expandAvatar}>
<img src={this.props.username} />
</div>
}
}
Example of a "dumb" AvatarComponent:
class AvatarComponent extends Component {
render () {
<div onClick={this.props.onExpandAvatar}>
{this.props.loading && <div className="spinner" />}
<img src={this.props.username} />
</div>
}
}
In the end I would say that "dumb", "stateless" and "pure" are quite different concepts that can sometimes overlap, but not necessarily, depending mostly on your use case.
i am not a genius over react, but from my understanding we can use each component in following situations
Stateless component -- these are the component which doesn't have life-cycle so those components should be used in rendering repeat element of parent component such as rendering the text list which just displays the information and doesn't have any actions to perform.
Pure component -- these are the items which have life-cycle and they will always return the same result when a specific set of props is given. Those components can be used when displaying a list of results or a specific object data which doesn't have complex child elements and used to perform operations which only impact itself. such a displaying list of user cards or list of products cards( basic product info) and only action user can perform is click to view detail page or add to cart.
Normal Components or Complex Components -- I used term complex component because those are usually the page level components and consists lot of children components and since each of child can behave in its own unique way so you can't be 100% sure that it will render the same result on given state. As I said usually these should be used as container components
React.Component is the default "normal" component. You declare them using the class keyword and extends React.Component. Think of them as a class, with lifecycles methods, event handlers and whatever methods.
React.PureComponent is a React.Component that implements shouldComponentUpdate() with a function that does a shallow comparison of its props and state. You have to use forceUpdate() if you know the component has props or state nested data that changed and you want to re-render. So they're not great if you need components to re-render when arrays or objects you pass as props or set in your state change.
Functional components are ones that don't have lifecycle functions. They're supposedly stateless, but they're so nice and clean that we now have hooks (since React 16.8) so you can still have a state. So I guess they're just "clean components".
Recently I've been writing more and more of my react components in a functional style, since most of them don't need the lifecycle functions or state. Inside my components (which are, again, just functions) I define helper functions - onClick functions and all that jazz. But now I'm thinking if this is good practice? Since the function is called for each render, does it recreate all the internal functions? I'm curious about memory loss and whether I'm doing this wrong.... An example of a component:
import React from 'react';
import { connect } from 'react-redux';
import ProductSearch from '../Plan/components/ProductSearch';
const BlockedProducts = (props) => {
const onSelectProduct = (product_key) => {
console.log(product_key);
};
return (
<ProductSearch onSelectProduct={ onSelectProduct } />
);
};
export default connect()(BlockedProducts);
Yes, there will definitely be some performance hit by virtue of the fact that you're declaring a function every single time you render BlockedProducts. How efficiently that gets cleaned up from garbage collection I don't know, but it seems best not to press your luck.
Functional components in React are really meant to be completely stateless and not "do" anything except be presentational. The ideal functional component just returns some JSX/HTML to render, no bells and whistles. In my opinion, a functional component should ONLY have a return, and as soon as you start adding interior functions it should be upgraded to a full fledged React class.
You could move the onSelectProduct declaration from BlockedProducts scope by putting it above component. It will make a closure to component's scope, because BlockedProducts declaration will be in the same scope with onSelectProduct.
I don't think that it will cause some perf issues. I do agree with #jered - a stateless components should be as simple as possible, so try to don't make any business logic there.
I have came to the same question recently. https://github.com/yannickcr/eslint-plugin-react/issues/357 Daniel discusses that this approach will increase GC workload, so he uses class components instead.
I would argue that first of all class components are for handling lifecycle and state and they also have impact to performance by creating backing bean, that suppose to deal with lifecycles and state.
Therefore I would use functional class instead and create class components when real performance issues will arise
Btw, 10 months have passed, I am curious which approach you have finally sticked with?