React Hook useState 视图不更新

发布时间 2023-03-30 01:30:50作者: Himmelbleu

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]);
}

上面利用扩展运算符合并了新旧数组,并创建新的数组,与原数组不相关,因此可以实现视图更新。