【问题标题】:React useState didn't catch previous stateReact useState 没有捕捉到以前的状态
【发布时间】:2019-08-30 09:14:39
【问题描述】:

我在更新组件中的状态时遇到了一些问题: 我有几个可以选择和选择的服务,开始异步加载这个服务,所以我想显示一些加载状态,但是当有多个服务并且我选择两个(非常快)我之前的状态是错误的

当我快速点击第一个和第二个服务时,它们都需要加载 但是当我点击第二个服务时的实际加载状态 === {0: false, 1: true} 必须是 {0: true, 1: true} 但我不知道为什么第一个服务加载 === false

有代码

生成初始状态

    const [loadingState, setLoadingState] = React.useState(
        availableServices.reduce((loadingState, service) => {
            loadingState[service.id] = false;

            return loadingState;
        }, {})
    );

实际状态

    useEffect(() => {
        console.log('actual loading state', loadingState);
    }, [Object.keys(loadingState).map(id => id)]);

句柄选择函数

    const onSelect = useCallback(
        async (id: string) => {
            const selectedServicesIds = selectedServices.map(service => service.id);
            setAddingInProgress(true);
            console.log('set to true', loadingState);
            setLoadingState({ ...loadingState, ...{ [id]: true } });
            // set to true {0: false, 1: false}
            // actual loading state {0: true, 1: false}
            // click on second service
            // set to true {0: false, 1: false}
            // actual loading state {0: false, 1: true} <-- there is need to be {0: true, 1: true}

            if (selectedServicesIds.includes(id)) {
                selectedServicesIds.splice(selectedServicesIds.findIndex(serviceId => serviceId === id), 1);
                await updateServices(selectedServicesIds);
            } else {
                selectedServicesIds.push(id);
                await updateServices(selectedServicesIds);
            }
            setAddingInProgress(false);
            console.log('set to false', loadingState);
            setLoadingState({ ...loadingState, ...{ [id]: false } });
        },
        [selectedServices]
    );

【问题讨论】:

  • 问题是什么?

标签: reactjs react-hooks


【解决方案1】:

我认为这会奏效

    const onSelect = useCallback(
        async (id: string) => {
            const selectedServicesIds = selectedServices.map(service => service.id);
            setAddingInProgress(true);
            console.log('set to true', loadingState);
            setLoadingState(prev => ({ ...prev, ...{ [id]: true } }));
            // set to true {0: false, 1: false}
            // actual loading state {0: true, 1: false}
            // click on second service
            // set to true {0: false, 1: false}
            // actual loading state {0: false, 1: true} <-- there is need to be {0: true, 1: true}

            if (selectedServicesIds.includes(id)) {
                selectedServicesIds.splice(selectedServicesIds.findIndex(serviceId => serviceId === id), 1);
                await updateServices(selectedServicesIds);
            } else {
                selectedServicesIds.push(id);
                await updateServices(selectedServicesIds);
            }
            setAddingInProgress(false);
            console.log('set to false', loadingState);
            setLoadingState(prev => ({ ...prev, ...{ [id]: false } }));
        },
        [selectedServices]
    );

【讨论】:

  • 谢谢!不知道 setState 可以接收以前状态的回调。
【解决方案2】:

由于没有要回答的问题,我将快速回顾一下:

  1. [Object.keys(loadingState).map(id =&gt; id)] 中的 map 始终会创建一个新对象,因此您的效果将在每次渲染时执行,这是不希望的
  2. 您的回调返回一个 Promise,它应该可以工作,但它不适合分配异步处理程序

【讨论】:

    猜你喜欢
    • 2022-08-24
    • 2022-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多