i'm creating a wordpress plugin with React - haven't really ever used React before this, so I'm probably misunderstanding something crucial but this is what I'm trying to achieve: You have a button that creates a question for a quiz and then to every button you can add multiple solutions:
DOMquestions = questions.map((question) =>
<div>
<div>
{question.qIdTitle}
</div>
<div>
Type: {question.qTypeTitle}
</div>
<div>
Question title
<input type={"text"} onChange={question.title = handleTextInputChange}></input>
</div>
<div>
Question description
<input type={"text"} onChange={question.desc = handleTextInputChange}></input>
</div>
<button onClick={() => question.addS(question)}>Add a solution</button>
<div>
{
question.solutions.map((solution) =>
{
return <div>Solution data and fields appear here</div>
}
)
}
</div>
</div>
);
console.log(DOMquestions);
ReactDOM.render(<div class='w-100'>{DOMquestions}</div>, qc);
The idea is that every Function object has an array full of solution objects inside of it
the addS function pushes a new solution object to the array - so I already have my array The question is how should I go about rendering it on screen Thanks in advance
CodePudding user response:
1- Put the "questions" array in a state.
2- Make a function "updateQuestions" to update the questions array in state
3- Add array index here "DOMquestions = questions.map((question, index)"
4- Send the index of the question object to this function on onClick. "onClick={() => updateQuestions(index)}"
5- now in updateQuestions grab the question object from "questions" array through this index like
questionsArray = {...questions} const question = questionsArray[index]
and add attach the question object to function .adds questionsArray[index].addS(question)
6- Now update the questions state with this new questionArray setQuestions([...questionsArray])
CodePudding user response:
There are multiple mistakes you have made, let's go over them one by one:
- From React 18, the
render
method has been deprecated in favor ofcreateRoot
method, and this is how you can implement it:
const DOMquestions = () => <div>...</div>;
const root = ReactDOM.createRoot(qc);
root.render(
<DOMquestions />
);
- It's better to make your main
DOMquestions
a functional component, in order to use any of the react functionalists like state, callbacks etc
const DOMquestions = () => {
return (
// ...
)
}
- When mapping an array in react you must use
key
property, this helps react track which items have changed.
questions.map((question) => (
<div key={question.qIdTitle}>
{/* ... */}
</div>
)
- Your input change events is written incorrectly, and I'm not sure what you were trying to achieve, but if I will rewrite it I would use
useCallback
for the input change and it would look like this. Also<input />
is self-closing tag, you don't have to use</input>
const handleTitleInputChange = React.useCallback(event => {
question.title = event.target.value;
});
return (
<input value={question.title} onChange={handleTitleInputChange} />
)
Finally, let's bring those all together in one place:
const DOMquestions = () => {
const handleTitleInputChange = React.useCallback((event, question) => {
question.title = event.target.value;
});
const handleDescInputChange = React.useCallback((event, question) => {
question.desc = event.target.value;
});
return (
questions.map((question) =>
<div key={question.qIdTitle}>
<div>
{question.qIdTitle}
</div>
<div>
Type: {question.qTypeTitle}
</div>
<div>
Question title
<input value={question.title} onChange={event => handleTitleInputChange(event, question)} />
</div>
<div>
Question description
<input value={question.desc} onChange={event => handleDescInputChange(event, question)} />
</div>
<button onClick={() => question.addS(question)}>Add a solution</button>
<div>
{question.solutions.map((solution) => (
<div key={solution.id}>Solution data and fields appear here</div>
))}
</div>
</div>
)
)
}
const root = ReactDOM.createRoot(qc);
root.render(
<DOMquestions />
);