javascript - React Hooks:即使我使用扩展运算符、prevState 等,状态也会重置为空数组
问题描述
单词:简而言之:我的items
状态正在重置为[]
每点击一个新的复选框,我不明白为什么。但相反,我想使用扩展运算符和useState
钩子将新项目推送到数组中,因此它是一个对象数组。
当前行为的详细信息:我正在创建一个对象并使用所有(我的意思是所有)方式的 ReactuseState
钩子将其设置为状态,如下所示:setItems((prevState) => [...prevState, { [evt.target.value]: evt.target.checked }]);
当我检查一个项目时,它被添加并items
成为一个对象数组(它被添加到和重来一遍不是问题;稍后我会添加一个检查)。但是问题出在:当我单击一个新复选框时,items
数组被设置回并没有[]
与 prev 连接items
——即使我正在使用prevState
、spread 运算符、一个箭头函数作为包装器,以及所有这些爵士乐。
期望的行为:每次我选中一个复选框时,我都想更新items []
以将一个新对象推入其中,该对象代表曾经被选中的所有项目。在您说有关复制的任何内容之前:我将添加检查以查看某个项目是否已在数组中,如果是则更新它。在我将所有内容添加items
到购物车之前,我将删除所有带有checked = false
状态的对象。
你能帮我理解我在这里缺少什么反应生命周期基础吗?为什么会这样?我该如何解决?
代码:发生这种情况的地方:
简化版InputComponent
const InputComponent = ({ type, itemId, handleSearchQuery, onSubmit }) => {
const [items, setItems] = useState([]);
const captureInput = (evt) => {
if (evt.target.type === 'checkbox') {
setItems((prevState) => [...prevState, { [evt.target.value]: evt.target.checked }]);
}
};
const renderCheckbox = () => {
return (
<form>
<input type={type} name={itemId} value={itemId} onChange={setItem} />
<input name={itemId} type='submit' value='Add to Cart' />
</form>
);
};
return (
<div className='input-bar'>
{renderCheckbox()}
</div>
);
};
export default InputComponent;
使用此组件的位置:
import React from 'react';
import InputComponent from './InputComponent';
import './ResultsRenderer.css';
function ResultsRenderer({ data }) {
const renderListings = () => {
let listings = data ? data.Search : null;
return listings
? listings.map((item) => {
return (
<div className='cart-row'>
<InputComponent type='checkbox' className='cart-checkbox' itemId={item.imdbID} />
<div key={item.imdbID} className={item.imdbID}>
<img src={`${item.Poster}`} alt={item.Title} />
<div>
Title<em>{item.Title}</em>
</div>
<div>{item.Year}</div>
<em>{item.imdbID}</em>
</div>
</div>
);
})
: null;
};
return <>{renderListings()}</>;
}
export default ResultsRenderer;
解决方案
items
状态做得很好,你误解了情况。
您在items
内部使用 stateInputComponent
并且每个listings item
都有一个InputComponent
,每个都有自己的items
,我认为您的意思是使用Componentitems
内部的 stateResultsRenderer
来追逐所有 selected items
。
这是您需要做的更改:
const InputComponent = ({ type, itemId, setItems }) => {
const captureInput = (evt) => {
if (evt.target.type === "checkbox") {
setItems((prevState) => [
...prevState,
{ [evt.target.value]: evt.target.checked }
]);
}
};
return (
<div className="input-bar">
<form>
<input
type={type}
name={itemId}
value={itemId}
onChange={captureInput}
/>
<input name={itemId} type="submit" value="Add to Cart" />
</form>
</div>
);
};
export default InputComponent;
function ResultsRenderer() {
const [items, setItems] = useState([]);
useEffect(() => {
console.log(items);
}, [items]);
const renderListings = () => {
let listings = [
{ itemId: 1, title: "Hello" },
{ itemId: 2, title: "World" }
];
return listings
? listings.map((item) => {
return (
<div className="cart-row">
<InputComponent
type="checkbox"
className="cart-checkbox"
itemId={item.itemId}
setItems={setItems}
/>
<div key={item.itemId} className={item.itemId}>
<div>
Title<em>{item.Title}</em>
</div>
</div>
</div>
);
})
: null;
};
return <>{renderListings()}</>;
}
这是工作演示:https ://codesandbox.io/s/boring-cookies-t0g4e?file=/src/InputComponent.jsx