[英]React useState overwritten even with spread
所以我有一个组件,我必须在其中进行 API 调用以获取一些具有我用于另一个异步 API 调用的 ID 的数据。 我的问题是我无法让异步 API 调用正常工作,通过传播 (...) 更新 state 以便可以在渲染中进行检查以显示与特定内容相关的特定阶段。
仅供参考:项目是一个无头 Drupal/React。
import WidgetButtonMenu from '../WidgetButtonMenu.jsx';
import { WidgetButtonType } from '../../Types/WidgetButtons.tsx';
import { getAllInitaitives, getInitiativeTaxonomyTerm } from '../../API/Initiatives.jsx';
import { useEffect } from 'react';
import { useState } from 'react';
import { stripHTML } from '../../Utilities/CommonCalls.jsx';
import '../../../CSS/Widgets/WidgetInitiativeOverview.css';
import iconAdd from '../../../Icons/Interaction/icon-add.svg';
function WidgetInitiativeOverview(props) {
const [initiatives, setInitiatives] = useState([]);
const [initiativesStages, setInitiativesStage] = useState([]);
// Get all initiatives and data
useEffect(() => {
const stages = [];
const asyncFn = async (initData) => {
await Promise.all(initData.map((initiative, index) => {
getInitiativeTaxonomyTerm(initiative.field_initiative_stage[0].target_id).then((data) => {
stages.push({
initiativeID: initiative.nid[0].value,
stageName: data.name[0].value
});
});
}));
return stages;
}
// Call data
getAllInitaitives().then((data) => {
setInitiatives(data);
asyncFn(data).then((returnStages) => {
setInitiativesStage(returnStages);
})
});
}, []);
useEffect(() => {
console.log('State of stages: ', initiativesStages);
}, [initiativesStages]);
return (
<>
<div className='widget-initiative-overview-container'>
<WidgetButtonMenu type={ WidgetButtonType.DotsMenu } />
{ initiatives.map((initiative, index) => {
return (
<div className='initiative-container' key={ index }>
<div className='top-bar'>
<div className='initiative-stage'>
{ initiativesStages.map((stage, stageIndex) => {
if (stage.initiativeID === initiative.nid[0].value) {
return stage.stageName;
}
}) }
</div>
<button className='btn-add-contributors'><img src={ iconAdd } alt='Add icon.' /></button>
</div>
<div className='initiative-title'>{ initiative.title[0].value } - NID ({ initiative.nid[0].value })</div>
<div className='initiative-description'>{ stripHTML(initiative.field_initiative_description[0].processed) }</div>
</div>
);
}) }
</div>
</>
);
}
export default WidgetInitiativeOverview;
这是视频可视化的链接: https://vimeo.com/743753924 。 在视频中,您可以看到在页面刷新时,state 中没有数据,但如果我修改代码(例如放入空格)并保存它,数据会填充半秒并在组件中正确更新。
我尝试使用 spread 来确保 state 没有发生突变,但我仍在学习 React 的细节。
state 倡议工作正常,但话又说回来,这只是 1 个 API 调用然后设置数据。 InitiativeStages state 可以使用 X 数量的 API 调用,具体取决于在第一个 API 调用期间返回的倡议数量。
我不认为 API 调用对于这个问题是必要的,但如果需要,我可以参考它们。 同样,我认为这只是更新 state 的问题。
您传递给initData.map()
的 function 不会返回任何内容,因此您的await Promise.all()
正在等待一系列Promise.resolve(undefined)
.你有机会调用stages.push({... });
这就是为什么你setInitiativesStage([])
一个空数组。
你用const stages = [];
做什么并且stages.push()
内部的 stage.push( .then()
是一种反模式,因为它会产生像您这样的损坏代码。
我就是这样写效果的:
useEffect(() => {
// makes the request for a single initiative and transforms the result.
const getInitiative = initiative => getInitiativeTaxonomyTerm(
initiative.field_initiative_stage[0].target_id
).then(data => ({
initiativeID: initiative.nid[0].value,
stageName: data.name[0].value
}))
// Call data
getAllInitaitives()
.then((initiatives) => {
setInitiatives(initiatives);
Promise.all(initiatives.map(getInitiative))
.then(setInitiativesStage);
});
}, []);
这段代码仍然有一个缺陷(imo。)它首先更新setInitiatives
,然后开始让 API 自己调用 initiaives ,然后再更新setInitiativesStage
。 因此,这两种状态在一段时间内不同步。 您可能想延迟setInitiatives(initiatives);
直到其他 API 请求完成。
getAllInitaitives()
.then(async (initiatives) => {
const initiativesStages = await Promise.all(initiatives.map(getInitiative));
setInitiatives(initiatives);
setInitiativesStage(initiativesStages)
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.