如何在道具更改期间让组件重新渲染

how to let component rerender during props change

我想在 PRODUCTS 改变时(点击按钮时)实现效果,列表也会改变,第一个类别改变为“哈哈”。

整个objective就是让组件在props改变的时候重新渲染。但似乎它不起作用。下面是代码。

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

const FilterableProductTable = (props) =>{
    return (

        <ul>
            {props.products.map((product) =>
                (<li>{product.category}</li>)
            )}
        </ul>
    );
}

const PRODUCTS = [
    { category: 'Sporting Goods', price: '.99', stocked: true, name: 'Football' },
    { category: 'Sporting Goods', price: '.99', stocked: true, name: 'Baseball' },
    { category: 'Sporting Goods', price: '.99', stocked: false, name: 'Basketball' },
    { category: 'Electronics', price: '.99', stocked: true, name: 'iPod Touch' },
    { category: 'Electronics', price: '9.99', stocked: false, name: 'iPhone 5' },
    { category: 'Electronics', price: '9.99', stocked: true, name: 'Nexus 7' }
];

const Home = () => {
    const [productData, changeProduct] = useState(PRODUCTS);
    const handleClick = () => {
        PRODUCTS[0].category = 'haha';
        changeProduct(PRODUCTS);
        console.log(PRODUCTS);
    };
    return (
        <>
            <button onClick={handleClick}>haha</button>
            <FilterableProductTable products={productData} />
        </>
    );
};

export default Home;

您可以在这里尝试:

如何让 FilterableProductTable 在 props 变化期间重新渲染?

当您在函数组件中设置状态时,React 会在新旧状态之间进行 ===。如果它们相同,则 React 会跳过渲染。由于您正在改变状态,因此前后是相同的数组,并且跳过了渲染。

解决方法是让您的状态保持不变。不要修改旧数组,而是创建一个新数组:

const handleClick = () => {
  changeProducts(prev => {
    const next = [...prev];
    next[0] = {
      ...next[0],
      category: 'haha';
    }
    return next;
  });
}

当更改数组中的 属性 时,React 不会将其视为更改,您可以使用扩展运算符克隆数组并设置新数组:

changeProduct([...PRODUCTS])

forked codesandbox

useState 将触发 re-render,仅当其当前值不同于当前状态时。它将进行 Object.is=== 比较。在这里,您设置了与 defaultState 中相同的引用 PRODUCTS,传递给 changeProduct 的值也具有与 PRODUCTS 相同的引用,这不会触发 re-render.

引用自 React DOCS

If your update function returns the exact same value as the current state, the subsequent rerender will be skipped completely.

const handleClick = () => {
  const res = productData.map((prod,index) => index === 0 ? {...prod,category:"haha"} : prod)
  changeProduct(res);
  console.log(res);
};

map每次都会创建一个新数组。