skip to Main Content

I have a component with a single input element and I am creating multiple components by looping. Suppose I have created 3 components by looping and it creates 3 inputs as well. So I do I get the values of all the three input like input_values = [valueofFirstInput, valueofSecondInput, valueofThirdInput]

function Home(){
  const [multipleQuestions, setMultipleQuestions] = useState([0, 1, 2]);

  return(
     {multipleQuestions.map((data, index) => {
      return (
        <div key={data}>
       {<MultipleInputs />}</div>
       )
      })}              
  )
}
function MultipleInputs() {
  function getinputValues(e) {
    e.target.value;
  }

  return <input onChange={(e) => getinputValues(e)} />;
}

2

Answers


  1. You can make your custom input component a controlled input by allowing the value and a callback for when the value changes to be passed in as props. Then, you can store all the input values in state.

    function Home(){
      const [multipleQuestions, setMultipleQuestions] = useState([0, 1, 2]);
      return multipleQuestions.map((data, index) => (
        <div key={index}>
           <CustomInput value={data} onChange={val => setMultipleQuestions([...multipleQuestions.slice(0, index), val, ...multipleQuestions.slice(index + 1)])}/>
        </div>
      ));
    }
    function CustomInput({onChange, value}){
        return <input value={value} onChange={e => onChange(e.target.value)}/>;
    }
    
    Login or Signup to reply.
  2. Generally you would treat those child components as controlled components which can share state. You would create a handler in the parent component and pass down a reference to it to each input component. They can then call that handler when their change event is fired.

    In this example I’ve created a sample dataset which I’m passing into Home. Each object in the dataset has an id (which we can use for a key instead of the map index), a name, and a label.

    In Home we create state for the input values. This is an object which pairs a key (the input name) with a value.

    Here also is the handler which destructures the name and value from the changed input, and updates the state with that information.

    (There is also a useEffect which logs the changes to the state as each input is changed so you can see it working.)

    When we iterate over the dataset we return an Input element passing down the name, type, value (obtained from state), and label as props along with the handler reference. In the Input component we attach these props as attributes to the input element, and assign the handler to the onChange listener.

    const { Fragment, useEffect, useState } = React;
    
    function Home({ questions }) {
      
      // Initialise the state for the inputs
      const [ inputs, setInputs ] = useState({});
      
      // Destructure the name and value from
      // the changed input element, and update
      // the state
      function handleInput(e) {
        const { name, value } = e.target;
        setInputs(prev => {
          return { ...prev, [name]: value };
        });
      }
    
      // Added simply to show the changing state
      useEffect(() => {
        console.log(JSON.stringify(inputs));
      }, [inputs]);
    
      // `map` over the dataset to produce a
      // series of labels/inputs
      return (
        <main>
          {questions.map(question => {
    
            const { id, name, label } = question;
    
            return (
              <Input
                key={id}
                type="text"
                name={name}
                label={label}
                value={inputs[name]}
                handleInput={handleInput}
              />
    
            );
          })}            
        </main>
      );
    
    }
    
    // Return an input using the props
    // passed down to it to identify it
    function Input(props) {
    
      const {
        name,
        label,
        type,
        value,
        handleInput
      } = props;
    
      return (
        <Fragment>
          <label htmlFor={name}>{label}</label>
          <input
            id={name}
            type={type}
            name={name}
            onChange={handleInput}
          />
        </Fragment>
      );
    
    }
    
    const data = [
      { id: 1, name: 'name', label: 'What is your name?' },
      { id: 2, name: 'age', label: 'How old are you?' },
      { id: 3, name: 'location', label: 'Where are you?' }  
    ];
    
    const el = document.getElementById('root');
    const root = ReactDOM.createRoot(el);
    
    root.render(<Home questions={data} />);
    label { display: block; }
    .as-console-wrapper { height: 25px; }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script>
    <div id="root"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search