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?
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.
I've been reading and watching videos on Redux and seeing a lot of debate about managing state in components or with Redux. What I'm not seeing is anything about managing state completely outside of components with standard global variables.
For example, I could set a global state variable like this:
let state = {
player: {
username: "BillyBob",
score: 100
}
}
Then in a React component, I could have something like this:
incrementScore() {
state.player.score += 1
props.update()
}
Then in App.js, I could have this:
update() {
this.forceUpdate()
}
I realize that I'd still have to pass the update function down through the tree, but I'd at least be able to set functions at the component level and not have to worry about passing multiple pieces of state and functions to child components.
I'm new to React, but the only downside I can think of is not being able to require propTypes. Is there anything else I'm missing?
EDIT: Per request that I clarify the question, are there any major downsides to the implementation above that I should be considering that would affect even a relatively simple app?
If you look at the implementation of redux or some other state management library out there (for example mobx or mobx-state-tree), basically all of them maintain the state outside of the component as a standalone object.
However, to detect changes and trigger re-render efficiently, they implement a HOC, it's connect in redux and inject in mobx, what the HOC (higher order component) does is to wrap your component inside another component that have access to the global state, and pass the part of the state require by your component via its props. This way, the component only re-render when the data required by it changes.
Compared with these popular library approach, there are couple problems with your proposed solution.
The first is using forceUpdate, basically, the last thing you might want to do is to call forceUpdate on the root node of your app, think about scenario when someone type in an input and the whole app re-render every single keystroke.
The second will be passing an update function down to multiple level of children, it will be fine if you have only 1 or 2 nested component, but will be a big problem one your app grows. As your app grows and your state become more complex, it might not be the best idea to have a single update function to control the whole state object.
React exists to solve the problem of creating a user interface that is composed of several indepentent pieces that can be developed in parallel and can seamlessly interact with each other.
If you are going to use global namespace to define your state then you are going to bypass most of the key features of React such as:
1. Lifecycle methods
2. Virtual DOM
3. Controlled Components
4. Rendering Optimizations
In a nutshell, you are going to end up with all the overhead costs of running React while missing out on its benefits.
The 'catch' in learning a new framework or paradigm is to understand how to define the problem in such a way that it leads to path of least resistance. This can be achieved by introducing a constraint and then solving the problem within that constraint.
By favoring vanilla JavaScript for state management, you are not giving React and Redux a fair chance.
I've created a library exactly for this use case :)
Simple 💪 fast ⚡️ and small 🎈 (500 bytes) global state management for React which can be used outside of a React component too!
https://github.com/web-ridge/react-ridge-state
Stick to redux, dont complicate things for yourself :)
I'm just discovering the amazing benefits of using HOC in my react projects.
My question is there any performance hit for calling multiple HOC functions on a component?
Example
export default withState(withLabel(withTheme(MyComponent)))
This will of course only render one component, however looking at my react dev tools i can see the outputted HOC components three levels deep. Is this something to be wary of or is there a better approach to calling multiple HOC on a component?
Your syntax is equivalent to doing:
<StateProvider>
<LabelProvider>
<ThemeProvider>
<MyComponent />
</ThemeProvider>
</LabelProvider>
</StateProvider>
The performance hit will come from how these HOC are implemented. You would probably have to look at each of them.
Example:
Theme Provider HOCs usually store a bunch of colors and variables in the React context. So using only one at the very root of your App is enough.
One could imagine that your LabelProvider simply adds an extra span before your component, in which case there is little to worry about
StateProviders like redux usually inject props in the component just below them so you don't really have a choice but to use them whenever you need state objects.
In conclusion, there are no hard rules. Your main focus should be on understanding what these HOC do and to try to limit unnecessary re-renders of your app.
I wouldn't use that. It's complicated to understand where the props come from, when you are looking at your MyComponent component. There are much more downsides using this pattern. Anyway if you decided to use HOCs use it in a right way e.g.
const withDetails = Component => {
const C = props => {
// do something
}
// assign display & wrapped names - easier to debug
C.displayName = `withRouter(${Component.displayName))`
C.WrappedComponent = Component;
return C;
}
Instead of using HOCs i suggest looking at render props react pattern. It's well explained in a Use a Render Prop! article by Michael Jackson (react-router creator).
Hope it makes sense.
I normally post code related stuff on Stack, but this is more a question about what the general thoughts of the community are.
There seems to be a lot of people advocating the use Redux with React to manage data/state, but while reading and learning both I've come across something that doesn't quite look right.
Redux
At the bottom of this page: http://redux.js.org/docs/basics/UsageWithReact.html (Passing the Store) it recommends using the "Magic" of React 'Context'.
One option would be to pass it as a prop to every container component. However it gets tedious, as you have to wire store even through presentational components just because they happen to render a container deep in the component tree.
The option we recommend is to use a special React Redux component called to magically make the store available to all container components...
React
On the React Context page (https://facebook.github.io/react/docs/context.html) it has a warning at the top:
Context is an advanced and experimental feature. The API is likely to change in future releases.
Then at the bottom:
Just as global variables are best avoided when writing clear code, you should avoid using context in most cases...
Do not use context to pass your model data through components. Threading your data through the tree explicitly is much easier to understand...
So...
Redux recommends using the React 'Context' feature rather than passing the store along down to each component via 'props'. While React recommends the opposite.
Also, it seems that Dan Abramov (the creator of Redux) now works for Facebook (the creator of React), just to confuse me more.
Am I reading all this right..?
What is the general current consensus on this issue..?
Context is an advanced feature and is subject to change. In some cases its conveniences outweigh its downsides so some libraries like React Redux and React Router choose to rely on it despite the experimental nature.
The important part here is the word libraries. If context changes its behavior, we as library authors will need to adjust. However, as long as the library doesn’t ask you to directly use the context API, you as the user shouldn’t have to worry about changes to it.
React Redux uses context internally but it doesn’t expose this fact in the public API. So you should feel much safer using context via React Redux than directly because if it changes, the burden of updating the code will be on React Redux and not you.
Ultimately React Redux still supports always passing store as a prop so if you want to completely avoid context, you have that choice. However I would say this is impractical.
TLDR: Avoid using context directly unless you really know what you are doing. Using a library that happens to rely on context internally is relatively safe.
I don't know about others, but I prefer using react-redux's connect decorator to wrap my components so that only the props from the store I need are passed into my component. This justifies the use of context in a sense because I am not consuming it (and I know, as a rule, any code that I am in charge of will not consume it).
When I test my components, I test the non-wrapped component. Because react-redux only passed the props I needed on that component, I now know exactly what props I need when I'm writing the tests.
I suppose the point is, I don't ever see the word context in my code, I don't consume it, so to a certain degree, it doesn't affect me! This doesn't say anything about Facebook's "experimental" warning.. If context disappeared, I'd be just as screwed as everyone else until Redux was updated.
There's an npm module that makes it really easy to add redux to the react context
https://github.com/jamrizzi/redux-context-provider
https://www.npmjs.com/package/redux-context-provider
import React, { Component } from 'react';
import ReduxContextProvider from 'redux-context-provider';
import createStore from './createStore';
import actions from './actions';
import Routes from './routes';
export default class App extends Component {
render() {
return (
<ReduxContextProvider store={store} actions={actions}>
<Routes />
</ReduxContextProvider>
);
}
}
React ships with all the features you need to handle your state without a single additional library. Most of your application's states should not be global as they live just fine in a useState or useReducer or custom hook next to your components.
So before you dive into the world of advanced state management (e.g. Redux), consider using the tools React ships with out of the box.
If you are interested in learning a bit more about this, I'd recommend this article by Andy Fernandez, which dives into the details on Redux: Context API vs Redux