Yes you should, if you want the easy way, You can use it everywhere and it might be the easiest way for optimization.
But you should know how React works, you can write your component in a way that they don't need re-render. but sometime it might be harder than using memo
React will re-render every child, you can prevent this by using memo, but what if you write the parent in a way that doesn't need re-render at all?
There is some design that you can use to achieve this.
1. Move states from parent to children
Imagine we have a page for creating Blog posts. There is a big state in the parent that store everything about the post form. So when every single form element changes, all components will be re-render. Now you can use 'memo' to prevent this, but that is not the way react works.
First, we need to move the state into some store with a selector, you can use something like redux or other store management, I prefer using context with use-sync-external-store/with-selector.
Now the parent should NOT use this store at all, for example, something like this is wrong
[postState, dispatch] = usePostStore();
Because you subscribe to all changes in the store and with anything change all component will re-render again.
To make this work we don't need to use state at the parent (you still can use dispatch to change the state and move logic to reducer so you have access to state there), so something like this should work:
[, dispatch] = usePostStore((state) => null)
so how to manage children? for example for the Editor component in the post editing page, we can subscribe only to state.content
[{content}, dispatch] = usePostStore(({content}=> ({content}))
So when the content changed we only re-render the Editor component, not all component trees.
You can keep doing this with every single form element but it's not that much necessary. you can handle some elements in one component. Of course, when something changes all components will re-render but these are small components so the speed does not matter that much.
For example, can put content and title in the Editor component and it should be ok.
2. Pass component as a child of a parent component
Here is example: https://playcode.io/1763824
The other thing you can do is pass the component as a child to another component, in this way when the parent component needs to re-render react will not re-render the child.
For example, we can do this:
function Post() { return ( <EditorComponent> <FilePicker /> </EditorComponent> ); }
So now when EditorComponent need to re-render React WILL NOT re-render FilePicker, it will only re-render when Post need that and it should happen very few time since the post has minimum state and we tried to put all state in children instead of parent.
Lets see your example with store
// NameComponent.js import React from "react"; const NameComponent = () => { const [name, dispatch]= useStore((store) => store.name); return <div>{name}</div> }; export default NameComponent; // CountComponent.js import React from "react"; const CountComponent = () => { const [count , dispatch]= useStore((store) => store.count ); return <div>{count}</div> }; export default CountComponent; // App.js import React from "react"; import NameComponent from "./NameComponent"; import CountComponent from "./CountComponent"; function App() { const [, dispatch] = useStore((store) => null); handleClick = e => { // since we don't have access to `count` here we dispatch it // in reducer we have access to count so we can increase it by one dispatch('increaseCount'); }; return ( <div> <NameComponent name={this.state.name} /> <CountComponent count={this.state.count} /> <button onClick={this.handleClick}>Add Count</button> </div> ); } const reducer = (state, {type, payload})=> { if(type === 'increaseCount'){ return { ...state, count: state.count + 1, } } return state; }
As you can see we don't need state in the parent component, and because of that we don't need memo because the component will only re-render when they subscribed value of the state changes. But what if you need? just extract that to another child component.
Only use state in parent component when lots of component need to change if the value changes
For other options let's look at react document:
In practice, you can make a lot of memoization unnecessary by following a few principles:
- When a component visually wraps other components, let it accept JSX as children. This way, when the wrapper component updates its own state, React knows that its children don’t need to re-render.
- Prefer local state and don’t lift state up any further than necessary. For example, don’t keep transient state like forms and whether an item is hovered at the top of your tree or in a global state library.
- Keep your rendering logic pure. If re-rendering a component causes a problem or produces some noticeable visual artifact, it’s a bug in your component! Fix the bug instead of adding memoization.
- Avoid unnecessary Effects that update state. Most performance problems in React apps are caused by chains of updates originating from Effects that cause your components to render over and over.
- Try to remove unnecessary dependencies from your Effects. For example, instead of memoization, it’s often simpler to move some object or a function inside an Effect or outside the component.