I'm trying to a large React form, but each input in the form is complex and has a complex state. I keep the state of all of the inputs in a parent
component, and each input is wrapped in a child
component. I have a state array in parent that contains the current value of the state for all of the input elements. Currently, every time there's an onChange
in the input, I try to reset the entire state array in the parent via setState()
. This was okay with up to 5 inputs, but once I got above that (like a hundred inputs), I started to notice some serious lag in the program. Please note: the program will also allow you to rearrange, delete
, and add
inputs, so the state needs to accommodate those changes Ie. the first input could swap positions with the 2nd input or be inserted right after the 10th input.
My objective is to find a way to optimize the performance of this onChange. Ultimately, I don't really need the data to be in the parent
component, I just need to collect the values for the inputs when I click save
at the bottom of the page.
Just to reiterate, I have two components.
A Parent Component
A Child Component
The Child component is basically an input
where users can write hundreds of lines of text.
The Parent component contains 100s of the children and essentially looks like this:
export default function Parent(props) {
const [state, setState] = useState(createDummyData());
useEffect(() => {});
const onInputChange = (value, index) => {
var tempValue = [...state];
tempValue[index] = value;
setState(tempValue);
};
return (
<>
<div style={{ display: "flex", flexDirection: "column" }}>
{state.map((item, index) => (
<Child
value={state[index].content}
index={index}
onChange={onInputChange}
/>
))}
<button style={{backgroundColor: "red"}}>save input data</button>
</div>
</>
);
}
The child component looks like this
export default function Child(props) {
useEffect(() => {});
const onChange = event => {
props.onChange(event.target.value, props.index);
};
return (
<>
<input value={props.value} onChange={onChange} />
</>
);
}
I haven't found a simple way around this. Some seem to suggest using Redux, others seem to say use a combination of useMemo
and useEffect
to prevent rerenders. Your help would be much appreciated.
One thing I noticed is that if I try to keep individual state within the Child components, they render onChange
much faster. This is probably because it doesn't have to setState for the parent state array each time. If possible, I'd like to be able to simply go through and grab the state of the child nodes when I click save. Would I use a ref
in this case? Is it possible to do it without a ref?
I'd also like to AVOID using onBlur()
just for the purpose of this project
The codesandbox is copied down below for reference: https://codesandbox.io/s/cocky-knuth-jm8n6?fontsize=14
Created example with similar functional components and dummy data:
https://codesandbox.io/s/recursing-cdn-q4vx0
Have to create Child component with local item state and sync with main array. Added Delete and Add.
Work with object arrays as your sample.