I am experiencing an issue with useState. Below is the code running in codesandbox
https://codesandbox.io/s/kmznl0345r
Here is the code itself;
import React, { Fragment, useState } from "react";
import ReactDOM from "react-dom";
type FormElem = React.FormEvent<HTMLFormElement>;
interface ITodo {
text: string;
complete: boolean;
}
export default function App(): JSX.Element {
const [value, setValue] = useState<string>("");
const [todos, setTodos] = useState<ITodo[]>([]);
const handleSubmit = (e: FormElem): void => {
e.preventDefault();
addTodo(value);
setValue("");
};
const addTodo = (text: string): void => {
const newTodos: ITodo[] = [...todos, { text, complete: false }];
setTodos(newTodos);
};
const completeTodo = (index: number): void => {
const newTodos: ITodo[] = todos;
newTodos[index].complete = !newTodos[index].complete;
setTodos(newTodos);
};
return (
<Fragment>
<h1>Todo List</h1>
<form onSubmit={handleSubmit}>
<input
type="text"
value={value}
onChange={e => setValue(e.target.value)}
required
/>
<button type="submit">Add Todo</button>
</form>
<section>
{todos.map((todo: ITodo, index: number) => (
<Fragment key={index}>
<div>{todo.text}</div>
<button type="button" onClick={() => completeTodo(index)}>
{" "}
{todo.complete ? "Incomplete" : "Complete"}{" "}
</button>
</Fragment>
))}
</section>
</Fragment>
);
}
const root = document.getElementById("root");
ReactDOM.render(<App />, root);
When the complete button is clicked it only runs the completeTodo
function once, and it doesn't run again even though the setTodos function is run and the todos are updated.
This used to work in react 16.7.0-alpha-2
but now with version 16.8.1
it seems not to update.
Let me know any suggestions you have, and once again here is the code running in codesandbox;
You are currently mutating the todo
object in your completeTodo
function. If you instead create a new array with all the elements in todos
and create a new object where complete
is toggled it will work as expected.
const completeTodo = (index: number): void => {
const newTodos: ITodo[] = [...todos];
newTodos[index] = {
...newTodos[index],
complete: !newTodos[index].complete
};
setTodos(newTodos);
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.