reactjs - react : Hook not triggering when parent component changes boolean value passed to child

标签 reactjs

所以我有一个负责渲染项目列表的父级。单击该项目时,它将向父级发送一个事件,该事件将在 map 上记录选择状态。如果选择,它会将选定状态传递给子级,以便它可以更改样式。这是父级的代码:

export default function CreateYourMixProductsList(props: ProductsInterface) {
    const selectedProducts: Map<number, Product> = new Map<number, Product>();

function onProductClick(product: Product): void {
    selectedProducts.set(product.id, product);
}

return (
    <>
        <List sx={{width: '100%', bgcolor: 'background.paper'}}>
            {props?.products?.map(product => (
                <ProductListItem key={product.id} product={product}
                                 selected={selectedProducts.has(product.id)}
                                 onClick={(product) => onProductClick(product)} />
            ))}
        </List>
    </>
);

和 child

export default function ProductListItem(props: ProductProps) {
    const [selected, setSelected] = React.useState(false);

    function onClick(product: Product) {
       props.onClick(product);
    }

    useEffect(() => {
        setSelected(!selected);
    }, [props.selected]);

    return (
        <>
            <ListItemButton alignItems="flex-start" onClick={event => {onClick(props.product)}} selected={props.selected ? selected : false}>
//omitted code to keep it short

useEffect 仅在渲染时触发,而据我了解,每次传递的 props 是不可变变量时都应该触发它。我在这里缺少什么?

最佳答案

让我们打开这个:

为什么 useEffect 没有运行?

每次依赖项数组中的变量发生更改时, Hook 都会重新运行。您的钩子(Hook)不会再次运行,因为 props.selected 的值没有更改。 您只需在组件中记录该值即可轻松验证这一点。

为什么 props.selected 没有改变?

您的点击处理程序正确设置了 map 上的值。但是,React 无法识别映射内设置的新值。该组件永远不会重新渲染,也不会再次调用 selectedProducts.has()。所以 props.selected 的值确实还是一样。

如何让 React 识别您的更改?

首先,您应该避免在组件中声明这样的状态。每次渲染此组件时,它都会重新声明其中定义的所有变量(selectedProducts 将始终设置为新的空映射)。使用 react hook api相反。

要使变量保持不变并具有反应性,您只需将其与 useState() 一起使用,就像在子组件中所做的那样。例如:

...
const [selectedProducts, setSelectedProducts] = useState<Map<number, Product>>(new Map<number, Product>());

function onProductClick(product: Product): void {
    selectedProducts.set(product.id, product);
    // Note how we are re-setting the variable to make React aware of the change!
    setSelectedProducts(new Map(selectedProducts));
}
...

需要注意的是,Reacts useState 钩子(Hook)会将值与三等号 (===) 进行比较,以确定是否应该触发重新渲染。由于 JavaScript 的性质(其中变量仅保存对对象的引用),在 Map 上设置新值不会更改其引用。要触发重新渲染,您必须替换 map 。

创建新对象的计算成本很低,因此大多数时候这不会导致任何问题。

关于reactjs - react : Hook not triggering when parent component changes boolean value passed to child,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70230207/

相关文章:

reactjs - Material UI 在数组中选择多项选择

javascript - 如何将本地自定义字体应用于 Stripe Elements?

javascript - Reactjs : setState doesn't assign value to state

javascript - Laravel + ReactJS 在 Blade View 中松散组件。一个好的做法?

reactjs - React-router - 无法读取未定义的属性 'query'

javascript - 在 Jest 和 Enzyme 测试中触发 useEffect

javascript - 使用 getUserMedia 访问音频输入

javascript - 无法使用 Rails-Webpacker React Frontend 从 Rails Active Storage 中搜索视频

reactjs - 将分页与react-bootstrap表一起使用

javascript - react : passing component's state to container