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

Javascript Reactjs中setState()之后未定义(使用钩子),javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我学会了自己做出反应。请解释为什么会出现这种情况。请原谅我的文章太多,我尽量把问题解释清楚。谢谢本质:通过钩子设置初始状态: const [pokemon, setPokemon] = useState({ img: "", name: "", types: [], abilities: [], moveList: [], weight: "", height: "", description: "", genus: "

我学会了自己做出反应。请解释为什么会出现这种情况。请原谅我的文章太多,我尽量把问题解释清楚。谢谢本质:通过钩子设置初始状态:

  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
            };
          });
        })

      await Axios({
        method: "GET",
        url: urlPokemonSpecies
      }).then(result => {
         let description = "";
         result.data.flavor_text_entries.forEach(flavor => {
          if (flavor.language.name === "en") {
           description = flavor.flavor_text;
          }
        });
        let genus = "";
        result.data.genera.forEach(genera => {
         if (genera.language.name === "en") {
          genus = genera.genus;
         }
        });
        const evolutionURL = result.data.evolution_chain.url;
        const eggGroups = result.data.egg_groups.map(
          egg_group => egg_group.name
        );
        const chanceToCatch = Math.round(
          (result.data.capture_rate * 100) / 255
        );
        setPokemon(pokemon => {
          return {
            ...pokemon,
            description: description,
            genus: genus,
            chanceToCatch: chanceToCatch,
            evolutionURL: evolutionURL,
            eggGroups: eggGroups
          };
        });
      });
    };
    fetchData();
  }, [urlPokemonAPI, urlPokemonSpecies]);
问题特别出现在
eggGroups
上(对于
能力
类型
的处理相同,则不存在此类问题)。这就是当我想将数据输出到一个页面,作为
egggroup:{pokemon.eggGroups}
时,数据会正常显示,但只要我想输出
eggGroups
以及
能力
类型
并用逗号(
join(',')
)-错误:
TypeError:pokemon.eggGroups未定义
。我决定通过控制台检查此事,并将此
eggGroups
键插入超时:


在某一点上,
eggGroups
变得未定义。。。为什么,我不明白。但是如果我单独设置状态,比如
const[egg,setEgg]=useState([]);卵(卵群)未观察到此类问题。为什么会这样?使用
类型
能力
一切都很好。提前谢谢。

钩子中的状态更新程序在更新状态时不会合并状态值,而是用新值替换旧值

因为您使用的状态更新程序像

 setPokemon(() => {
        return {
          img: img,
          name: name,
          weight: weight,
          types: types,
          abilities: abilities,
          moveList: moveList,
          height: height
        };
      });
eggGroups
属性丢失,因此它变得未定义。您需要通过传播从回调中获得的先前状态值来更新它

setPokemon((prev) => {
        return {
          ...prev
          img: img,
          name: name,
          weight: weight,
          types: types,
          abilities: abilities,
          moveList: moveList,
          height: height
        };
      });

您的代码有问题,这是使用axios进行Wait的正确方法, 您需要像这样导入axios

从“axios”导入axios;
应使用承诺调用
wait
,然后它从api返回如下数据:

const result=wait axios.get(urlPokemonAPI);
这是与代码具有相同逻辑的代码段

useffect(()=>{
const fetchData=async()=>{
//从“axios”导入axios;
试一试{
const result=等待axios.get(urlPokemonAPI);
const pokemon=result.data;
口袋妖怪({
img:pokemon.sprites.front\u默认值,
名称:pokemon.name,
重量:数学圆(口袋妖怪重量/10),
类型:pokemon.types.map(i=>i.type.name),
能力:口袋妖怪.abilities.map(i=>i.ability.name),
moveList:pokemon.moves.map(i=>i.move.name),
高度:口袋妖怪。高度/10
});
const result2=等待axios.get(urlPokemonSpecies);
const data=result2.data;
让描述=”;
data.flavor\u text\u entries.forEach(i=>{
const lang=i.language.name
如果(lang==“en”){
description=i.flavor\u文本;
}
});
让属=”;
data.generals.forEach(i=>{
const lang=i.language.name;
如果(lang==“en”){
属=一属;
}
});
设置口袋妖怪(口袋妖怪=>{
返回{
精灵宝可梦
描述
属
chancetocch:Math.round((data.capture_rate*100)/255),
进化URL,
eggGroups:data.egg\u groups.map(g=>g.name)
};
});
}捕获(e){
控制台日志(e);
}
};
fetchData();
},[urlPokemonAPI,urlPokemonSpecies]);
您是否看到另一个问题:您两次调用setPokemon,让我们再次重写它:

useffect(()=>{
const fetchData=async()=>{
//从“axios”导入axios;
试一试{
const result=等待axios.get(urlPokemonAPI);
const data1=result.data;
const result2=等待axios.get(urlPokemonSpecies);
const data2=result2.data;
函数描述(数据){
让描述=”;
data.flavor\u text\u entries.forEach(i=>{
const lang=i.language.name
如果(lang==“en”){
description=i.flavor\u文本;
}
});
返回说明;
}
函数(数据){
让属=”;
data.generals.forEach(i=>{
const lang=i.language.name;
如果(lang==“en”){
属=一属;
}
});
归属;
}
口袋妖怪({
img:data1.sprites.front\u默认值,
名称:data1.name,
重量:数学四舍五入(数据1.weight/10),
类型:data1.types.map(i=>i.type.name),
能力:data1.abilities.map(i=>i.ability.name),
moveList:data1.moves.map(i=>i.move.name),
高度:数据1.1/10,
描述:resolveDescription(数据2),
属:属(数据2),
chancetocch:Math.round((数据2.capture_rate*100)/255),
进化url:data2.evolution\u chain.url,
eggGroups:data2.egg\u groups.map(g=>g.name)
});
}捕获(e){
控制台日志(e);
}
};
fetchData();
},[urlPokemonAPI,urlPokemonSpecies]);

函数some()用于测试数组是否至少有一个元素通过了条件。我不理解代码,您是想使用.forEach()循环吗?谢谢您的评论。我在forEach上重播了我可以