我自己学习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
};
});
})
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
引起的(对abilities
和types
的处理相同,就没有这样的问题)。这就是当我想将数据<div> Egg Group: {pokemon.eggGroups} </div>
正常显示到页面上,但又想输出eggGroups
以及abilities
和{{ 1}}以逗号(types
)分隔-错误:join ( ',')
。我决定通过控制台检查此问题,并将此TypeError: pokemon.eggGroups is undefined
键塞入超时:
在某个时候,eggGroups
变得不确定...为什么,我听不懂。但是,如果我像eggGroups
那样单独设置状态,则不会观察到此问题。为什么会这样呢? const [egg, setEgg] = useState ([]); setEgg (eggGroups);
和types
一切都很好。预先谢谢你。
答案 0 :(得分:1)
hook中的状态更新程序不会在更新状态时合并状态值,而是仅将旧值替换为新值
因为您使用的是状态更新程序,例如
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
};
});
答案 1 :(得分:1)
您的代码有问题,这是使用axios等待的正确方法, 您需要像这样导入axios
import axios from 'axios';
await
应该以一个promise调用,然后它像这样从api返回数据:
const result = await axios.get(urlPokemonAPI);
这是与您的代码具有相同逻辑的代码段
useEffect(() => {
const fetchData = async () => {
// import axios from 'axios';
try {
const result = await axios.get(urlPokemonAPI);
const pokemon = result.data;
setPokemon({
img: pokemon.sprites.front_default,
name: pokemon.name,
weight: Math.round(pokemon.weight / 10),
types: pokemon.types.map(i => i.type.name),
abilities: pokemon.abilities.map(i => i.ability.name),
moveList: pokemon.moves.map(i => i.move.name),
height: pokemon.height / 10
});
const result2 = await axios.get(urlPokemonSpecies);
const data = result2.data;
let description = "";
data.flavor_text_entries.forEach(i => {
const lang = i.language.name
if (lang === "en") {
description = i.flavor_text;
}
});
let genus = "";
data.genera.forEach(i => {
const lang = i.language.name;
if (lang === "en") {
genus = i.genus;
}
});
setPokemon(pokemon => {
return {
...pokemon,
description,
genus,
chanceToCatch: Math.round((data.capture_rate * 100) / 255),
evolutionURL,
eggGroups: data.egg_groups.map(g => g.name)
};
});
} catch (e) {
console.log(e);
}
};
fetchData();
}, [urlPokemonAPI, urlPokemonSpecies]);
您是否看到另一个问题:您两次调用setPokemon ,让我们再次重写:
useEffect(() => {
const fetchData = async () => {
// import axios from 'axios';
try {
const result = await axios.get(urlPokemonAPI);
const data1 = result.data;
const result2 = await axios.get(urlPokemonSpecies);
const data2 = result2.data;
function resolveDescription(data) {
let description = "";
data.flavor_text_entries.forEach(i => {
const lang = i.language.name
if (lang === "en") {
description = i.flavor_text;
}
});
return description;
}
function resolveGenus(data) {
let genus = "";
data.genera.forEach(i => {
const lang = i.language.name;
if (lang === "en") {
genus = i.genus;
}
});
return genus;
}
setPokemon({
img: data1.sprites.front_default,
name: data1.name,
weight: Math.round(data1.weight / 10),
types: data1.types.map(i => i.type.name),
abilities: data1.abilities.map(i => i.ability.name),
moveList: data1.moves.map(i => i.move.name),
height: data1.height / 10,
description: resolveDescription(data2),
genus: resolveGenus(data2),
chanceToCatch: Math.round((data2.capture_rate * 100) / 255),
evolutionURL: data2.evolution_chain.url,
eggGroups: data2.egg_groups.map(g => g.name)
});
} catch (e) {
console.log(e);
}
};
fetchData();
}, [urlPokemonAPI, urlPokemonSpecies]);