防止 api 在状态更新之前被调用

prevent api from being called before state is updated

我有一个对象列表。我想在对象的位置字段更改后进行 api 调用。因此,为此,我有一个 useEffect,它具有 id、index 和 location 作为其依赖项。我已经为该位置设置了一个空检查,如果该位置不为空,我想进行 api 调用。但问题是,即使位置为空,也会调用 api,我最终得到 400。我该如何解决这个问题并在位置不为空时拨打电话?

    const [plants, setPlants] = useState([
        {
            name: 'Plant 1',
            id: uuidv4(),
            location: '',
            coords: {},
            country: '',
            isOffshore: false,
        }
    ]);
    const [locationIDObject, setlocationIDObject] = useState({
        id: plants[0].id,
        index: 0
    });

    const handlePlantLocChange = (id, index, value) => {
        setPlants(
            plants.map(plant => 
                plant.id === id
                ? {...plant, location: value}
                : plant
            )
        )
        setlocationIDObject({
            id: id,
            index: index
        })
    }

    const getCoords = (id, index) => {
        axios.get('http://localhost:3002/api/coords', {
            params: {
                locAddress: plants[index].location
            }
        }).then((response) => {
            if(response.status === 200) {
                handlePlantInfoChange(id, PlantInfo.COORD, response.data)
            }
        })
    }

    const handler = useCallback(debounce(getCoords, 5000), []);

    useDeepCompareEffect(() => {
        if(plants[locationIDObject.index].location !== '')
            handler(locationIDObject.id, locationIDObject.index);
    }, [ locationIDObject, plants[locationIDObject.index].location])

    return (
        <div className='plant-inps-wrapper'>
            {
                plants.map((item, idx) => {
                    return (
                        <div key={item.id} className="org-input-wrapper">
                            <input placeholder={`${item.isOffshore ? 'Offshore' : 'Plant ' + (idx+1) + ' location'}`} onChange={(e) => handlePlantLocChange(item.id, idx, e.target.value)} value={item.isOffshore ? 'Offshore' : item.location} className="org-input smaller-input"/>
                        </div>
                    )
                })
            }
        </div>
    )

我认为当你的变量值发生变化时你的 useCallback 没有更新,这就是问题所在:

虽然检查是正确的,但是调用是针对变量的旧值进行的。您应该更新 useCallback 的依赖项:

console.log(plants) inside getCoords 可能会帮助您调查。

试试这个:

 const handler = useCallback(debounce(getCoords, 5000), [plants]);

原来问题出在我的去抖功能上。我不知道到底是什么问题,但是当我用这个替换去抖功能时,一切都按预期工作:

    useEffect(() => {
        console.log("it changing")
        const delayDebounceFn = setTimeout(() => {
            getCoords(locationIDObject.id, locationIDObject.index)
        }, 4000)

        return () => clearTimeout(delayDebounceFn)
    },[...plants.map(item => item.location), locationIDObject.id, locationIDObject.index])