防止 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])
我有一个对象列表。我想在对象的位置字段更改后进行 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])