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
Advertisement
Answer
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 functionalities 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 /> );