Table 值在反应中没有改变
Table values does not change in react
我正在从 API 获取数据并从前端更改值以在 table 中显示它。我正在获取 object 的列表并将其存储在一个状态中,并在 html table 中显示该状态中的 object。 table 有一个显示布尔值的复选框。如果该值为 true,则复选框中的 defaultChecked 为 true。 table header 中有一个复选框,用于选中或取消选中所有项目。
下面是我取的jsonobject
{
completed: false
id: 1
title: "delectus aut autem"
userId: 1
}
如果我勾选了 table header 中的复选框,我想在所有 200 个项目中将 completed
设置为 true
。
以下是将所有项目设置为 true 或 false 的代码。
const checkAllHandler = (e) => {
let val = e.target.checked;
console.log(val);
let allTodoList = [];
if (val === true) {
if (todo.length > 0) {
for (let index = 0; index < todo.length; index++) {
const newObject = {
userId: todo[index].userId,
id: todo[index].id,
title: todo[index].title,
completed: true,
};
allTodoList.push(newObject);
}
setTodo(allTodoList);
}
} else if (val === false) {
if (todo.length > 0) {
for (let index = 0; index < todo.length; index++) {
const newObject = {
userId: todo[index].userId,
id: todo[index].id,
title: todo[index].title,
completed: false,
};
allTodoList.push(newObject);
}
setTodo(allTodoList);
}
}
};
当我控制 todo
状态时,所有值都更新为 true 或 false,但它没有显示在 table 上。
table 具有过滤功能。如果我过滤一个词然后返回,那么整个 table 的值都在改变。我想在单击复选框时显示更改,而不是在搜索和返回时显示更改。我该怎么做?
该组件的完整代码如下。
const DataTable = () => {
const { loading, items } = useSelector((state) => state.allData);
// console.log(items)
const dispatch = useDispatch();
// const history = useNavigate();
const [searchText, setsearchText] = useState("");
const [todo, setTodo] = useState(items);
console.log("todo");
console.log(todo);
const [isFetch, setisFetch] = useState(false);
const [checkedloading, setcheckedLoading] = useState(false);
const [isChecked, setisChecked] = useState(false);
console.log(isChecked);
useEffect(() => {
const setDataToState = () => {
if (loading === false) {
setTodo(items);
}
};
setDataToState();
}, [loading]);
useEffect(() => {
dispatch(getData());
// setTodo(items)
// console.log(items)
}, [dispatch]);
//etTodo(items)
const handleSearch = (event) => {
//let value = event.target.value.toLowerCase();
setsearchText(event.target.value);
};
const onChangeHandler = (e, item) => {
console.log(e.target.checked);
console.log(item);
if (e.target.checked === true) {
// const item = todo.filter(x=> x.id === id)
// console.log("added")
// console.log(item)
for (let index = 0; index < todo.length; index++) {
if (todo[index].id === item.id) {
console.log(todo[index]);
console.log("deleting");
todo.splice(index, 1);
console.log("deleted");
const newObject = {
userId: item.userId,
id: item.id,
title: item.title,
completed: true,
};
console.log("adding updated object");
todo.splice(index, 0, newObject);
console.log("added");
console.log(todo);
}
}
} else {
// const item = todo.filter(x=> x.id === id)
// console.log("removed")
// console.log(item)
for (let index = 0; index < todo.length; index++) {
if (todo[index].id === item.id) {
console.log(todo[index]);
console.log("deleting");
todo.splice(index, 1);
console.log("deleted");
const newObject = {
userId: item.userId,
id: item.id,
title: item.title,
completed: false,
};
console.log("adding updated object");
todo.splice(index, 0, newObject);
console.log("added");
console.log(todo);
}
}
}
};
const onSubmitHandler = () => {
localStorage.setItem("items", JSON.stringify(todo));
};
const getItem = () => {
const items = localStorage.getItem("items");
console.log("local storage items");
console.log(JSON.parse(items));
};
const checkAllHandler = async (e) => {
const { checked } = e.target;
console.log(checked);
setTodo((todos) =>
todos.map((todo) => ({
...todo,
completed: checked,
}))
);
};
return (
<>
{console.log("todo in render")}
{console.log(todo)}
<div className={styles.container}>
<div className={styles.top}>
<div className={styles.search_bar}>
<input
type="text"
onChange={(e) => handleSearch(e)}
placeholder="search by name"
/>
</div>
</div>
<div className={styles.btn_container}>
<button onClick={onSubmitHandler}>Submit</button>
</div>
<div className={styles.data_table_container}>
{checkedloading === false ? (
<>
<div className={styles.data_table}>
{loading || todo === null || todo === undefined ? (
<>
<p>Loading!!</p>
</>
) : (
<>
<table>
<tr>
<th>ID</th>
<th>userId</th>
<th>Title</th>
<th>
<>
Completed
<input type="checkbox" onChange={checkAllHandler} />
</>
</th>
</tr>
<tbody>
{todo
.filter((val) => {
if (searchText === "") {
return val;
} else if (
val.title.toLowerCase().includes(searchText)
) {
return val;
}
})
.map((item) => (
<>
<tr key={item.id}>
<td>{item.id}</td>
<td>{item.userId}</td>
<td>{item.title}</td>
<td>
<input
type="checkbox"
defaultChecked={item.completed}
onClick={(e) => onChangeHandler(e, item)}
/>
</td>
</tr>
</>
))}
</tbody>
</table>
</>
)}
</div>
</>
) : (
<>Loading</>
)}
</div>
</div>
</>
);
};
代码沙盒link:https://codesandbox.io/s/flamboyant-proskuriakova-60t19
我在这段代码中没有发现任何明显的问题,但它非常冗长。除了分配的 completed
布尔值外,两个逻辑分支都是相同的。在 React 中更新数组时,通常使用 functional state updates 来制作 先前状态 的浅表副本,而不是回调范围内可能关闭的任何状态。
示例:
const checkAllHandler = (e) => {
const { checked } = e.target;
console.log(checked);
setTodo(todos => todos.map(todo => ({
...todo,
completed: checked,
})));
};
如果从这里更新 table 还有进一步的问题,那么请添加其余的组件代码和您认为相关的任何其他代码。
更新
none 复选框输入在 table 中发生变化的原因是因为您使用了 defaultChecked
属性,这使得这些输入完全 不受控制 输入。它们在安装时采用初始 item.completed
值,除非您与复选框交互,否则不会从那里更改。
如果你想让他们从changes/updates响应到todo
状态,那么他们应该被转换成完全controlled 输入并使用 checked
属性。
<input
type="checkbox"
checked={item.completed}
onClick={(e) => onChangeHandler(e, item)}
/>
更新#2
onChangeHandler
中的 Array.prototype.splice
改变了单个复选框输入。 .splice
进行就地突变。同样,应该使用功能状态更新来浅拷贝先前的状态并通过 id
.
检查匹配的 todo
对象
const onChangeHandler = (e, item) => {
const { checked } = e.target;
setTodo((todos) =>
todos.map((todo) =>
todo.id === item.id
? {
...todo,
completed: checked
}
: todo
)
);
};
我正在从 API 获取数据并从前端更改值以在 table 中显示它。我正在获取 object 的列表并将其存储在一个状态中,并在 html table 中显示该状态中的 object。 table 有一个显示布尔值的复选框。如果该值为 true,则复选框中的 defaultChecked 为 true。 table header 中有一个复选框,用于选中或取消选中所有项目。
下面是我取的jsonobject
{
completed: false
id: 1
title: "delectus aut autem"
userId: 1
}
如果我勾选了 table header 中的复选框,我想在所有 200 个项目中将 completed
设置为 true
。
以下是将所有项目设置为 true 或 false 的代码。
const checkAllHandler = (e) => {
let val = e.target.checked;
console.log(val);
let allTodoList = [];
if (val === true) {
if (todo.length > 0) {
for (let index = 0; index < todo.length; index++) {
const newObject = {
userId: todo[index].userId,
id: todo[index].id,
title: todo[index].title,
completed: true,
};
allTodoList.push(newObject);
}
setTodo(allTodoList);
}
} else if (val === false) {
if (todo.length > 0) {
for (let index = 0; index < todo.length; index++) {
const newObject = {
userId: todo[index].userId,
id: todo[index].id,
title: todo[index].title,
completed: false,
};
allTodoList.push(newObject);
}
setTodo(allTodoList);
}
}
};
当我控制 todo
状态时,所有值都更新为 true 或 false,但它没有显示在 table 上。
table 具有过滤功能。如果我过滤一个词然后返回,那么整个 table 的值都在改变。我想在单击复选框时显示更改,而不是在搜索和返回时显示更改。我该怎么做?
该组件的完整代码如下。
const DataTable = () => {
const { loading, items } = useSelector((state) => state.allData);
// console.log(items)
const dispatch = useDispatch();
// const history = useNavigate();
const [searchText, setsearchText] = useState("");
const [todo, setTodo] = useState(items);
console.log("todo");
console.log(todo);
const [isFetch, setisFetch] = useState(false);
const [checkedloading, setcheckedLoading] = useState(false);
const [isChecked, setisChecked] = useState(false);
console.log(isChecked);
useEffect(() => {
const setDataToState = () => {
if (loading === false) {
setTodo(items);
}
};
setDataToState();
}, [loading]);
useEffect(() => {
dispatch(getData());
// setTodo(items)
// console.log(items)
}, [dispatch]);
//etTodo(items)
const handleSearch = (event) => {
//let value = event.target.value.toLowerCase();
setsearchText(event.target.value);
};
const onChangeHandler = (e, item) => {
console.log(e.target.checked);
console.log(item);
if (e.target.checked === true) {
// const item = todo.filter(x=> x.id === id)
// console.log("added")
// console.log(item)
for (let index = 0; index < todo.length; index++) {
if (todo[index].id === item.id) {
console.log(todo[index]);
console.log("deleting");
todo.splice(index, 1);
console.log("deleted");
const newObject = {
userId: item.userId,
id: item.id,
title: item.title,
completed: true,
};
console.log("adding updated object");
todo.splice(index, 0, newObject);
console.log("added");
console.log(todo);
}
}
} else {
// const item = todo.filter(x=> x.id === id)
// console.log("removed")
// console.log(item)
for (let index = 0; index < todo.length; index++) {
if (todo[index].id === item.id) {
console.log(todo[index]);
console.log("deleting");
todo.splice(index, 1);
console.log("deleted");
const newObject = {
userId: item.userId,
id: item.id,
title: item.title,
completed: false,
};
console.log("adding updated object");
todo.splice(index, 0, newObject);
console.log("added");
console.log(todo);
}
}
}
};
const onSubmitHandler = () => {
localStorage.setItem("items", JSON.stringify(todo));
};
const getItem = () => {
const items = localStorage.getItem("items");
console.log("local storage items");
console.log(JSON.parse(items));
};
const checkAllHandler = async (e) => {
const { checked } = e.target;
console.log(checked);
setTodo((todos) =>
todos.map((todo) => ({
...todo,
completed: checked,
}))
);
};
return (
<>
{console.log("todo in render")}
{console.log(todo)}
<div className={styles.container}>
<div className={styles.top}>
<div className={styles.search_bar}>
<input
type="text"
onChange={(e) => handleSearch(e)}
placeholder="search by name"
/>
</div>
</div>
<div className={styles.btn_container}>
<button onClick={onSubmitHandler}>Submit</button>
</div>
<div className={styles.data_table_container}>
{checkedloading === false ? (
<>
<div className={styles.data_table}>
{loading || todo === null || todo === undefined ? (
<>
<p>Loading!!</p>
</>
) : (
<>
<table>
<tr>
<th>ID</th>
<th>userId</th>
<th>Title</th>
<th>
<>
Completed
<input type="checkbox" onChange={checkAllHandler} />
</>
</th>
</tr>
<tbody>
{todo
.filter((val) => {
if (searchText === "") {
return val;
} else if (
val.title.toLowerCase().includes(searchText)
) {
return val;
}
})
.map((item) => (
<>
<tr key={item.id}>
<td>{item.id}</td>
<td>{item.userId}</td>
<td>{item.title}</td>
<td>
<input
type="checkbox"
defaultChecked={item.completed}
onClick={(e) => onChangeHandler(e, item)}
/>
</td>
</tr>
</>
))}
</tbody>
</table>
</>
)}
</div>
</>
) : (
<>Loading</>
)}
</div>
</div>
</>
);
};
代码沙盒link:https://codesandbox.io/s/flamboyant-proskuriakova-60t19
我在这段代码中没有发现任何明显的问题,但它非常冗长。除了分配的 completed
布尔值外,两个逻辑分支都是相同的。在 React 中更新数组时,通常使用 functional state updates 来制作 先前状态 的浅表副本,而不是回调范围内可能关闭的任何状态。
示例:
const checkAllHandler = (e) => {
const { checked } = e.target;
console.log(checked);
setTodo(todos => todos.map(todo => ({
...todo,
completed: checked,
})));
};
如果从这里更新 table 还有进一步的问题,那么请添加其余的组件代码和您认为相关的任何其他代码。
更新
none 复选框输入在 table 中发生变化的原因是因为您使用了 defaultChecked
属性,这使得这些输入完全 不受控制 输入。它们在安装时采用初始 item.completed
值,除非您与复选框交互,否则不会从那里更改。
如果你想让他们从changes/updates响应到todo
状态,那么他们应该被转换成完全controlled 输入并使用 checked
属性。
<input
type="checkbox"
checked={item.completed}
onClick={(e) => onChangeHandler(e, item)}
/>
更新#2
onChangeHandler
中的 Array.prototype.splice
改变了单个复选框输入。 .splice
进行就地突变。同样,应该使用功能状态更新来浅拷贝先前的状态并通过 id
.
todo
对象
const onChangeHandler = (e, item) => {
const { checked } = e.target;
setTodo((todos) =>
todos.map((todo) =>
todo.id === item.id
? {
...todo,
completed: checked
}
: todo
)
);
};