I'm working on a React component setup where I have a parent component <MyComponent>
that receives three state values, and three separate controller components that each initialize with one of these values and a setter function.
Here's a simplified version of my code.
// Parent Component
<MyComponent
input_a={A}
input_b={B}
input_c={C}
/>
// State declarations
const [A, setA] = useState(1);
const [B, setB] = useState(1);
const [C, setC] = useState(1);
// Controller Components
<ElementA
initial={A}
setter={setA}
/>
<ElementB
initial={B}
setter={setB}
/>
<ElementC
initial={C}
setter={setC}
/>
In this setup, when I update one state value (for example, using setA
), all three controller components (ElementA
, ElementB
, and ElementC
) re-render—even though only the controller associated with the updated state should be affected. The state values serve as initial values for the controller components, and subsequent updates should ideally only affect <MyComponent>
.
I have considered using memoization (such as with React.memo), but it hasn't produced the desired effect in this case. I'm looking for an alternative approach or best practices to restructure or optimize the code so that only the component corresponding to the updated state re-renders, without relying on memoization.
upd: Thank you for your answers and suggestions. I finally decided to use MobX to manage my states, and it has made my life easier.
I also realized that I had been using memoization incorrectly, but even after fixing it, I still noticed some freezing in my animations.
I'm working on a React component setup where I have a parent component <MyComponent>
that receives three state values, and three separate controller components that each initialize with one of these values and a setter function.
Here's a simplified version of my code.
// Parent Component
<MyComponent
input_a={A}
input_b={B}
input_c={C}
/>
// State declarations
const [A, setA] = useState(1);
const [B, setB] = useState(1);
const [C, setC] = useState(1);
// Controller Components
<ElementA
initial={A}
setter={setA}
/>
<ElementB
initial={B}
setter={setB}
/>
<ElementC
initial={C}
setter={setC}
/>
In this setup, when I update one state value (for example, using setA
), all three controller components (ElementA
, ElementB
, and ElementC
) re-render—even though only the controller associated with the updated state should be affected. The state values serve as initial values for the controller components, and subsequent updates should ideally only affect <MyComponent>
.
I have considered using memoization (such as with React.memo), but it hasn't produced the desired effect in this case. I'm looking for an alternative approach or best practices to restructure or optimize the code so that only the component corresponding to the updated state re-renders, without relying on memoization.
upd: Thank you for your answers and suggestions. I finally decided to use MobX to manage my states, and it has made my life easier.
I also realized that I had been using memoization incorrectly, but even after fixing it, I still noticed some freezing in my animations.
Share Improve this question edited Feb 17 at 22:57 Антон Пименов asked Feb 1 at 22:43 Антон ПименовАнтон Пименов 751 silver badge6 bronze badges 4 |1 Answer
Reset to default 1By default, any change in state in a parent component will re-render the children.
setState enqueues changes to the component state. It tells React that this component and its children need to re-render with the new state. This is the main way you’ll update the user interface in response to interactions.
https://react.dev/reference/react/Component#shouldcomponentupdate
What you could do is create a React class with the shouldComponentUpdate method. This allows you granular control of how an update re-renders your component. You're in complete control here.
So in this case, unless ElementA's A prop is changed, it won't re-render. You could do the same for the others.
class ElementA extends Component {
shouldComponentUpdate (nextProps) {
// Rendering the component only if
// passed props value is changed
return nextProps.A !== this.props.A;
}
render() {
React.memo(function ElementA(...)) { ... }
should makeElementA
rerender only when its own hooks, context or props change, even if its parent rerenders. Perhaps in your case you are passing a new callback to it each time, instead of using useCallback? – cbr Commented Feb 2 at 20:15