React Hook useState 页面不刷新,基础类型的值没有这个困扰,对象、数组要麻烦点。
App 组件有两个子组件,该组件使用了状态提升管理两个子组件依赖的数据,子组件 ProductList 点击按钮之后需要更新 trolleyList 的长度。
App.tsx:
function App() {
const [trolleyList, setTrolleyList] = useState<IProductList[]>([]);
const [productList, setProductList] = useState(products);
function handleInsert(newVal: IProductList) {
// 不更新
trolleyList.push(newVal);
setTrolleyList(trolleyList]);
}
return (
<div>
<ProductList productList={productList} onInsert={handleInsert} />
<BottomMenu count={trolleyList.length} />
</div>
);
}
子组件点击按钮之后,通过回调函数向上传递数据给父组件,通知更新数据(子组件与父组件的通信)。
ProductList.tsx:
export default function ProductList(props: {
productList: IProductList[];
onInsert: (e: IProductList) => void;
}) {
function handleClick(index: number) {
props.onInsert(props.productList[index]);
}
return (
<div className="f-c-c">
{props.productList.map((e, i) => (
<Card
hoverable
key={e.name}
className="w-60 mr-4"
cover={<img className="h-60" src={e.cover} />}
>
<div className="size-1.2 font-bold">{e.name}</div>
<div className="size-0.5 text-ellipsis line-clamp-2 mt-4">
{e.desc}
</div>
<div className="text-end color-red font-bold mt-4">¥{e.price}</div>
<div className="text-end mt-4">
<Button type="primary" size="small" onClick={() => handleClick(i)}>
<span className="size-0.5">加入购物车</span>
</Button>
</div>
</Card>
))}
</div>
);
}
目前问题是数据更新了,视图不更新,打开 DevTools 查看 state 也没有发生更新。对于数组、对象等类型的值,我们需要合并它们,而不能向基础类型的值直接传递给 setState
更新视图。
修改父组件的 handleInsert
函数代码:
function handleInsert(newVal: IProductList) {
setTrolleyList([...trolleyList, newVal]);
}
上面利用扩展运算符合并了新旧数组,并创建新的数组,与原数组不相关,因此可以实现视图更新。