I am trying to create a function that when gets called, it sets the state to the object {item: 'whatever the user types', list: [...list, todo]}; However, I don't know how to set the new state and return <li>{todo}</li>
at the same time. I have been stuck for a while so I'd appreciate if you can help me out.
const Todo = () => {
const [state, setState] = useState({ item: '', list: [] });
const setTodoValue = (e) => {
setState((previousState) => {
return { ...previousState, item: e.target.value };
});
};
const addTodo = () => {
setState((previousState) => {
return {
...previousState,
list: [...previousState.list, previousState.item],
};
});
};
return (
<div>
<input onChange={setTodoValue} type="text" />
<button onClick={addTodo}> </button>
{}
</div>
);
};
CodePudding user response:
You can't, or won't, update state and simultaneously return JSX. You enqueue a state update, React updates the state, and you describe how to render the JSX from the state. The render return should take the state
and map it to a bunch of list item li
elements.
For more details on rendering JSX from arrays, see Lists and Keys.
Example rendering state.list
into an unordered list:
const Todo = () => {
const [state, setState] = useState({ item: '', list: [] });
const setTodoValue = (e) => {
setState((previousState) => {
return { ...previousState, item: e.target.value };
});
};
const addTodo = () => {
setState((previousState) => {
return {
...previousState,
list: [...previousState.list, previousState.item],
};
});
};
return (
<div>
<input onChange={setTodoValue} type="text" />
<button type="button" onClick={addTodo}> </button>
<ul>
{state.list.map(todo => (
<li key={todo}>{todo}</li>
))}
</ul>
</div>
);
};