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.