Home > Software design >  How to push values into an array on submit btn click (react js)
How to push values into an array on submit btn click (react js)

Time:05-07

I have a questions form with custom inputs.

const Input = (props) => {
    return (
        <div>
            <label className={classes.label}>{props.label}
            <input className={classes.input} {...props}/>
            </label>
        </div>
    );
};

I get question list from server and set them into questions. Then I create a form for answer to these questions.

<form onSubmit = {onAnswersSubmit}>
     {questions?.map((item) =>
         <Input key={item.id} id={item.id} label={item.question}/>)}
      <Button> Submit </Button>
</form>

I'd like to push answers from inputs into array on submit button click, but have no idea how to do that.

CodePudding user response:

You should probably use state for this. One state for the array (I've called it state), and another to capture the answers to the questions (an object).

When an input's onChange listener is fired it calls handleChange. This function takes the name and value from the input (note: this example assumes that you can add a name property to the data you receive from your server), and then updates the answers state.

When the button is clicked the completed answers state (an object) gets added to the main state array.

const { useEffect, useState } = React;

function Example({ data }) {

  // Initialise the states
  const [ state, setState ] = useState([]);
  const [ answers, setAnswers ] = useState({});

  // Push the completed answers object into
  // the state array, then reset the answers state
  function handleClick() {
    setState([ ...state, answers ]);
    setAnswers({});
  }

  // Get the name and value from the input
  // and update the answers state
  function handleChange(e) {
    const { name, value } = e.target;
    setAnswers({ ...answers, [name]: value });
  }

  // Log the main state when it changes
  useEffect(() => console.log(state), [state]);

  return (
    <div>
      {data.map(obj => {
        const { id, name, question } = obj;
        return (
          <input
            key={id}
            name={name}
            placeholder={question}
            onChange={handleChange}
          />
        );
      })}
      <button onClick={handleClick}>Submit</button>
    </div>
  );

}

const data = [
  { id: 1, name: 'name', question: 'What is your name?' },
  { id: 2, name: 'age', question: 'How old are you?' },
  { id: 3, name: 'location', question: 'Where do you live?' }  
];

ReactDOM.render(
  <Example data={data} />,
  document.getElementById('react')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

CodePudding user response:

You can use the html input's onChange prop and pass an onChange function from your parent form to handle that like so:

// This is assuming this is inside a functional component

const [answers, setAnswers] = useState([]);

const onAnswerChange = useCallback((index, answer) => {
  setAnswers((oldAnswers) => {
    oldAnswers[index] = answer;
    return oldAnswers;
  });
}, [setAnswers]);

return 
<form onSubmit = {onAnswersSubmit}>
     {questions?.map((item, index) =>
         <Input key={item.id} 
                id={item.id} 
                label={item.question}
                value={answers[index] ?? ''}
                onChange={(e) => onAnswerChange(index, evt.target.value)}/>)}
      <Button> Submit </Button>
</form>

Then you can use the stored state in answers as part of your onAnswersSubmit callback.

  • Related