React useState未捕获先前的状态

时间:2019-08-30 09:14:39

标签: reactjs react-hooks

我在更新组件中的状态时遇到了一些麻烦: 我没有几个可以选择和选择的服务,开始异步加载该服务,所以我想显示一些加载状态,但是当有多个服务并且我选择两者时(很快)我就错了以前的状态< / p>

当我快速单击第一项和第二项服务时,它们都需要加载 但是当我单击第二项服务=== {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)]);

handleSelect函数

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

2 个答案:

答案 0 :(得分:2)

我认为这会起作用

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

答案 1 :(得分:0)

因为没有问题可以回答,所以我将快速复习一下:

  1. 您在map中的[Object.keys(loadingState).map(id => id)]始终会创建一个新对象,因此您会在每个不需要的渲染上执行效果
  2. 您的回调返回一个Promise,该Promise应该可以工作,但是对异步处理程序而言是不正常的