Background
So I have a simple example, a Form component (Parent) and multiple Input components (Children). Each individual Input component will have an useState
hook to initialize and manage its value's state.
Issue
As with most forms, I would like to submit all of the data to a backend for processing. However, the issue is that I cannot retrieve the state of value from each Child Input component.
// app.jsx
import Form from "./Form";
export default function App() {
return <Form />;
}
// Form.jsx
import React from "react";
import Input from "./Input";
const handleSubmit = (e) => {
e.preventDefault();
console.log("Wait, how do I retreive values from Children Inputs?");
};
const Form = () => {
console.log("Form render");
return (
<form onSubmit={handleSubmit}>
Sample Form
<Input initial={"username"} name={"user"} />
<Input initial={"email"} name={"email"} />
<button type="submit">Submit</button>
</form>
);
};
export default Form;
// Input.jsx
import React from "react";
import useInputValue from "./useInputValue";
const Input = ({ name, initial }) => {
const inputState = useInputValue(initial);
console.log(`${name}'s value: ${inputState.value}`);
return <input {...inputState} />;
};
export default Input;
Plausible Solution
Of course, I can lift the Input states up to the Form component, perhaps in an obj name values. However, if I do that, every time I change the Inputs, the Form will re-render, along with all of the Inputs.
To me, that is an undesirable side-effect. As my Form component gets bigger, this will be more costly to re-render all inputs (inside the form) every time one input changes.
Because of that, I would like to stick with my decision of having each individual input manage its own state, that way if one input changes, not all other input will re-render along with the Parent component.
Question
If each of the Child components manages its own state, could the Parent component access the value of that state and do actions (like form submission)?
Update
Many answers and comments mentioned that this is premature optimization and the root of all known evil; which I agree with, but to clarify, I am asking this question with a simple example because I wanted to find a viable solution to my current and more complex project. My web app has a huge form (where all states are lifted to the form level), which is getting re-rendered at every change in its inputs. Which seemed unnecessary, since only one input is changed at a time.
Update #2 Here is a codesandbox example of the issue I am having. There are two forms, one with all states managed by individual Child input components, and the other has all states lifted up in the form level. Try entering some values and check the console for log messages. One can see that with all states lifted to the form level, every change will cause both inputs to be re-rendered.
CodePudding user response:
If the parent needs to know about the childs state, you can
- move the state up. This is resolved by passing down a setState function that the child calls (the states data is available in the parent)
- use a context https://reactjs.org/docs/context.html
- use a state management library e.g. redux
In your simple case I'd go with 1)
CodePudding user response:
I think yes, you can share state. Also there are 3 options:
- I recommend you to use such library as Formik. It will help you in your case.
- You can share state using useState() hook as props.
- Use such tools as Redux Toolkit (if we are speaking about memoisation), useContext() and etc.
CodePudding user response:
If the thing you want is getting final values from input, assign ref to each input and access using emailRef.current.value in the submit function.