Eagle
Eagle

Reputation: 378

Get value from appended child component in React

I have a main react component which appends child components say <Child /> on button click

My Child component is of the format

<form>
    <input .... />
    <button type="submit">Submit</button>
<form>

Now I need to get the value of these input elements from every Child component which is appended but am not able to figure out a way to do so.

I won't know how many Child components would be added as the user can click the button any number of times to append yet another <Child /> so I can't have a fixed number of variables exported from the Child component to a variable in parent component.

Any suggestions would be highly appreciated.

Edit:

Code to append the child:

const [val, setVal] = useState([]);

const submit = () => {
    setVal([...val, <Child />]);
}
<Button onClick={submit}>Add Child</Button>
{val}

Since val is an array, it prints all the components inside it

Upvotes: 0

Views: 260

Answers (1)

luckongas
luckongas

Reputation: 1799

I took some liberties because I don't know what would be the expected output of all the forms.

What I basically did is to create a map-like structure where I will map each child form with its value/s (depending on your needs could be modified) and I passed a submit function to the child components in order to store the values on the parent.

In that way on a child submit I will be able to get the values passed from the child as well as its index.

Parent component

const Parent = () => {
  const [val, setVal] = useState([]);
  // Map like structure to store the values (is just an example, you can use whatever you want)
  const [mapOfValues, setMapOfValues] = useState({});

  // Pass submit function as prop
  const submit = () => {
    setVal([...val, <Child submit={onChildSubmit} />]);
  };

  // Submit function that stores the value for the child
  const onChildSubmit = (childIndex, value) => {
    setMapOfValues({
      ...mapOfValues,
      [childIndex]: value
    });
  };

  return (
    <div className="App">
      {val.map((value, index) =>
        // Key to prevent React warning and childIndex to map the value to the child form
        React.cloneElement(value, { key: index, childIndex: index })
      )}
      <button onClick={submit}>Add</button>
    </div>
  );
}

Child component

const Child = (props) => {
  const [value, setValue] = useState("");

  const submitForm = (e) => {
    e.preventDefault();
    props.submit(props.childIndex, value);
  };

  return (
    <form onSubmit={submitForm}>
      <input onChange={(e) => setValue(e.target.value)} value={value} />
      <button>Submit</button>
    </form>
  );
};

Once you are done, and you want to submit from the parent component, you could use a reduce, map or whatever you need to format the values as you want.

The link to the sandbox is this

If you have any other question let me know.

Upvotes: 2

Related Questions