如何使 setState 在 useEffect 中工作
Posted
技术标签:
【中文标题】如何使 setState 在 useEffect 中工作【英文标题】:How to make setState working in useEffect 【发布时间】:2021-03-10 19:08:02 【问题描述】:我正在使用 fetch API 从 API 中获取数据。 获取结果后,我想将 setState 设置为不工作的结果 这是获取结果的函数
export const random = (min, max) => Math.floor(Math.random() * (max - min)) + min;
export const getPokemons = async function ()
const pokemon = [];
for (let i = 0; i < 5; i++)
pokemon.push(fetch(`https://pokeapi.co/api/v2/pokemon/$random(1, 800)`));
return Promise.all(pokemon)
.then((data) =>
const parsedData = [];
data.forEach(async (d) =>
const resJson = await d.json()
parsedData.push(resJson);
);
return parsedData
)
.catch((err) =>
console.log(err);
);
;
导入的代码
const [stats,setStats] = useState([])
useEffect(()=>
generateTrio()
,[])
async function generateTrio()
const gTrio = await getPokemons();
setStats(gTrio)
console.log(stats,gTrio)
stats 这里是一个空数组,而 gTrio 是必需的结果我想在 setStats 中
【问题讨论】:
在调用setStats()
之后不要登录stats
,只需使用stats
来渲染你的元素,它就会像你期望的那样工作。
@PatrickRoberts 我确信即使在调用 setState
之后它也是一个空数组。 link to codesanbbox
【参考方案1】:
问题是双重的:
您正在将stats
记录在与您调用setStats()
相同的闭包中。请参阅useState set method not reflecting change immediately,了解为什么这样做会记录以前的状态。
您将async
函数传递给forEach()
的回调函数,该函数会在外部promise 与初始空数组解析后将数据推送到数组中。请参阅 Using async/await with a forEach loop 了解这种反模式的潜在缺陷。
您的 getPokemons()
从您的异步函数返回一个空数组,然后在它用于渲染您的 Main
组件之后异步填充它。
即使您在正确的闭包中记录 stats
,Chrome 的开发人员控制台输出也会令人困惑,因为它会显示该数组已填充,即使在记录时它是空的。有关此开发者控制台行为的更多信息,请参阅 Is Chrome's javascript console lazy about evaluating arrays?。
写getPokemons()
的一种正确方法是:
export const getPokemons = () => (
Promise.all(
Array.from( length: 5 , async () =>
const response = await fetch(`https://pokeapi.co/api/v2/pokemon/$random(1, 800)`);
return response.json();
)
)
);
编写Main
组件的正确方法是:
const Wrapper = styled.div``;
const Main = () =>
const [stats, setStats] = useState([]);
useEffect(() =>
const setPokemons = async () =>
setStats(await getPokemons());
;
setPokemons();
, []);
// console.log(stats);
const names = stats.map(item => (
<p key=item.id>item.name</p>
));
return (
<Wrapper>
names
</Wrapper>
);
export default Main;
【讨论】:
【参考方案2】:usestate 的设置函数不会立即同步设置状态。我认为它像异步方法。但这不仅仅是真正的原因。 您可以在类似主题中查看此消息。 https://***.com/a/58877875/12239744
【讨论】:
以上是关于如何使 setState 在 useEffect 中工作的主要内容,如果未能解决你的问题,请参考以下文章
如何将 setState 值插入 useEffect 挂钩?
如何在useEffect(func,[])中使用异步api调用中的setState钩子测试组件
React:如何使用功能性 usestate/useEffect 复制特定的组件类 setstate 回调示例?
在 useEffect 中处理 forEach 后调用 setstate
Flutter Hooks 使用 useEffect 获取数据 - 在构建期间调用 setState() 或 markNeedsBuild()