【问题标题】:How to use setState along with dispatch from redux - it re-renders whole component and restarts updated setState如何使用 setState 以及来自 redux 的调度 - 它重新渲染整个组件并重新启动更新的 setState
【发布时间】:2022-08-22 03:24:43
【问题描述】:

我有这个组件

const CheckboxColumn: FC<ICheckboxColumnProps> = ({ id_llamada }) => {
    // select  pickup

    const dispatch = useTypedDispatch();

    const [isPickupSelected, setIsPickupSelected] = useState(false);

    const selectPickup = (e: ChangeEvent<HTMLInputElement>) => {
        setIsPickupSelected(e.target.checked);

        dispatch(controlPickup(id_llamada));
    };

    return (
        <TableCell
            component={\'div\'}
            padding=\"checkbox\"
            sx={{ padding: \'0px 0px 0px 4px\' }}
            onClick={(e) => {
                e.stopPropagation();
            }}
        >
            <Checkbox
                color=\"primary\"
                checked={isPickupSelected ? true : false}
                // disabled={true}
                sx={{
                    padding: \'7px\',
                    \'&:hover\': {
                        backgroundColor: \'rgba(0, 0, 0, 0.06)\',
                    },
                }}
                onChange={selectPickup}
            />
        </TableCell>
    );
};

export default CheckboxColumn;

而且我需要能够选择一个表的行,还要将其信息发送到 redux,问题是,我不知道如何使用 setStatedispatch

目前正在发生的事情是,我的isPickupSelected 没有更新它的值,而是它实际上保存在我的减速器中的数据,并且当我评论dispatch(function()) 时,我的状态能够正常工作。

我一直在尝试寻找解决方案,其中之一是,我应该使用 useEffect 并且每当我的状态发生变化时,我应该调度该函数,它可以工作,但它会立即重新启动我的组件,还有我的isPickupSelected,所以我的状态不再更新,而是恢复到原来的值false

在这种情况下我该怎么办

  • 您能否提供您的代码并使用stackblitz.com 重现此问题?

标签: reactjs redux setstate redux-toolkit


【解决方案1】:

您不必在下面进行相等检查,因为 isPickupSelected 已经是 boolean 值。

checked={isPickupSelected ? true : false}

尝试简单地使用:

<Checkbox
  color="primary"
  checked={isPickupSelected}
  ...

此外,鉴于复选框只能选中或取消选中,您实际上可以这样做:

const selectPickup = () => {
  setIsPickupSelected(!isPickupSelected) // instead of `e.target.checked`

这样,当用户单击复选框时,状态设置器会将isPickupValue 设置为与当前值相反的值(切换)。

让我知道这是否能解决您的问题?干杯

【讨论】:

    【解决方案2】:

    您的调度如何更新状态与您的 setIsPickupSelected 之间的区别在于,您的调度状态依赖于前一个状态值来确定下一个状态值,而您的设置器依赖于 UI 元素值。该 UI 元素值由 isPickupState 控制,因此当单击复选框时,传入的值将是您从 e.target.checked 获得的值。要解决此问题,您需要与 UI 元素分开控制该状态。您已经使用 isPickupSelected 状态变量执行此操作。

    此外,由于您的复选框组件是唯一使用状态的组件,因此您可以在每次复选框更改时保存您的 TableCell 重新渲染。您所要做的就是将该逻辑提升到一个单独的组件中。

    const ControlledCheckbox : FC<IControlledCheckboxProps> = () => {
    
        const dispatch = useTypedDispatch();
    
        const [isPickupSelected, setIsPickupSelected] = useState(false);
    
        const selectPickup = () => {
            setIsPickupSelected(!isPickupSelected);
    
            dispatch(controlPickup(id_llamada));
        };
        return <Checkbox
                    color="primary"
                    checked={isPickupSelected ? true : false}
                    // disabled={true}
                    sx={{
                        padding: '7px',
                        '&:hover': {
                            backgroundColor: 'rgba(0, 0, 0, 0.06)',
                        },
                    }}
                    onChange={selectPickup}
                />
    }
    
    const CheckboxColumn: FC<ICheckboxColumnProps> = ({ id_llamada }) => {
        return (
            <TableCell
                component={'div'}
                padding="checkbox"
                sx={{ padding: '0px 0px 0px 4px' }}
                onClick={(e) => {
                    e.stopPropagation();
                }}
            >
               <ControlledCheckbox />
            </TableCell>
        );
    };
    
    export default CheckboxColumn;
    

    【讨论】:

      【解决方案3】:

      解决方案 1:从 Checkbox 中删除选中的道具,使其不受控制的输入。

      // checked={isPickupSelected ? true : false}
      

      解决方案 2:在处理程序 func 中:

      setIsPickupSelected(prevState => !prevState)
      

      【讨论】:

        【解决方案4】:

        prop id_llamada 来自 Redux 商店吗?

        如果是这种情况,那么组件将重新渲染,从而将 isPickedUpSelected 设置回 false。为什么?我假设调度在父级别更新id_llamada 的值,导致渲染进程捕获更新并在组件传递回组件时重新渲染组件。

        以上将是组件状态未更新的根本原因,这就是为什么当您注释掉调度时状态更新起作用的原因。

        为避免这种情况,您可能希望使用 id_llamada 的存储值,而不是将其作为道具传递。也许您想了解Redux Selectors

        此外,作为与初始问题无关的观察结果,由于isPickupSelected 是一个布尔值,您可以将checked={isPickupSelected ? true : false} 简化为checked={isPickupSelected}

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-12-06
          • 2020-03-27
          • 2021-04-28
          • 2021-12-24
          • 2019-01-24
          • 2020-08-08
          • 1970-01-01
          相关资源
          最近更新 更多