在 Reactjs 中的 setState() 之后未定义(使用钩子)

我自己学习 react 和 js。请解释为什么会出现这种情况。PS:请原谅我的大文本,我试图尽可能清楚地解释问题。谢谢。事情的本质:通过钩子设置初始状态:


  const [pokemon, setPokemon] = useState({

    img: "",

    name: "",

    types: [],

    abilities: [],

    moveList: [],

    weight: "",

    height: "",

    description: "",

    genus: "",

    chanceToCatch: "",

    evolutionURL: ""

  });

此外,我发出 api 请求以从 useEffect 内部获取信息:


useEffect(() => {

    const fetchData = async () => {

      await Axios({

        method: "GET",

        url: urlPokemonAPI

      })

        .then(result => {

          const pokemonResponse = result.data;


          /* Pokemon Information */

          const img = pokemonResponse.sprites.front_default;

          const name = pokemonResponse.name;

          const weight = Math.round(pokemonResponse.weight / 10);

          const height = pokemonResponse.height / 10;

          const types = pokemonResponse.types.map(type => type.type.name);

          const abilities = pokemonResponse.abilities.map(

            ability => ability.ability.name

          );

          const moveList = pokemonResponse.moves.map(move => move.move.name);

          setPokemon(() => {

            return {

              img: img,

              name: name,

              weight: weight,

              types: types,

              abilities: abilities,

              moveList: moveList,

              height: height

            };

          });

        })

问题特别出现eggGroups(具有相同的处理abilities并且types没有这样的问题)。这就是当我想<div> Egg Group: {pokemon.eggGroups} </div>在数据正常显示时将数据输出到页面时发生的情况,但只要我想输出eggGroups以及abilities用types逗号(join ( ','))分隔 - 错误:TypeError: pokemon.eggGroups is undefined。我决定通过控制台检查这件事,并将这个eggGroups密钥塞进超时:

http://img3.mukewang.com/62a1d1f00001dfc918820501.jpg

在某些时候,eggGroups变得未定义......为什么,我无法理解。但是如果我单独设置状态,const [egg, setEgg] = useState ([]); setEgg (eggGroups);就不会观察到这样的问题。为什么会这样?一切都很好typesabilities。先感谢您。



慕神8447489
浏览 285回答 2
2回答

泛舟湖上清波郎朗

来自钩子的状态更新器在更新状态时不会合并状态值,而是用新值替换旧值由于您使用状态更新器,例如&nbsp;setPokemon(() => {&nbsp; &nbsp; &nbsp; &nbsp; return {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; img: img,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name: name,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; weight: weight,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; types: types,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; abilities: abilities,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; moveList: moveList,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; height: height&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; });eggGroups属性丢失,因此它变得未定义。您需要通过传播从回调获得的先前状态值来更新它setPokemon((prev) => {&nbsp; &nbsp; &nbsp; &nbsp; return {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...prev&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; img: img,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name: name,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; weight: weight,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; types: types,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; abilities: abilities,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; moveList: moveList,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; height: height&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; });

犯罪嫌疑人X

您的代码有问题,这是使用 axios 等待的正确方法,您需要像这样导入 axiosimport axios from 'axios';await应该用一个promise调用,然后它从api返回数据,如下所示:const result = await axios.get(urlPokemonAPI);这是与您的代码具有相同逻辑的代码片段useEffect(() => {&nbsp; &nbsp; const fetchData = async () => {&nbsp; &nbsp; &nbsp; &nbsp; // import axios from 'axios';&nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const result = await axios.get(urlPokemonAPI);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const pokemon = result.data;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setPokemon({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; img: pokemon.sprites.front_default,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name: pokemon.name,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; weight: Math.round(pokemon.weight / 10),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; types: pokemon.types.map(i => i.type.name),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; abilities: pokemon.abilities.map(i => i.ability.name),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; moveList: pokemon.moves.map(i => i.move.name),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; height: pokemon.height / 10&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const result2 = await axios.get(urlPokemonSpecies);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const data = result2.data;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let description = "";&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data.flavor_text_entries.forEach(i => {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const lang = i.language.name&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (lang === "en") {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; description = i.flavor_text;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let genus = "";&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data.genera.forEach(i => {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const lang = i.language.name;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (lang === "en") {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; genus = i.genus;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setPokemon(pokemon => {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...pokemon,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; description,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; genus,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; chanceToCatch: Math.round((data.capture_rate * 100) / 255),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; evolutionURL,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; eggGroups: data.egg_groups.map(g => g.name)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; } catch (e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log(e);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; };&nbsp; &nbsp; fetchData();}, [urlPokemonAPI, urlPokemonSpecies]);你看到另一个问题了吗:你调用了两次 setPokemon,让我们再重写一次:useEffect(() => {&nbsp; &nbsp; const fetchData = async () => {&nbsp; &nbsp; &nbsp; &nbsp; // import axios from 'axios';&nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const result = await axios.get(urlPokemonAPI);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const data1 = result.data;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const result2 = await axios.get(urlPokemonSpecies);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const data2 = result2.data;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; function resolveDescription(data) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let description = "";&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data.flavor_text_entries.forEach(i => {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const lang = i.language.name&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (lang === "en") {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; description = i.flavor_text;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return description;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; function resolveGenus(data) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let genus = "";&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data.genera.forEach(i => {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const lang = i.language.name;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (lang === "en") {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; genus = i.genus;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return genus;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setPokemon({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; img: data1.sprites.front_default,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name: data1.name,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; weight: Math.round(data1.weight / 10),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; types: data1.types.map(i => i.type.name),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; abilities: data1.abilities.map(i => i.ability.name),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; moveList: data1.moves.map(i => i.move.name),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; height: data1.height / 10,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; description: resolveDescription(data2),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; genus: resolveGenus(data2),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; chanceToCatch: Math.round((data2.capture_rate * 100) / 255),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; evolutionURL: data2.evolution_chain.url,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; eggGroups: data2.egg_groups.map(g => g.name)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; } catch (e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log(e);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; };&nbsp; &nbsp; fetchData();}, [urlPokemonAPI, urlPokemonSpecies]);
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript