在 mount 中多次调用 react setState
calling react setState multiple times in mount
无法理解在 React 中使用 setState 挂载组件的最佳实践。我有一个应用程序,returns 每一代口袋妖怪的初始口袋妖怪。每一代都有自己的 axios.get() 方法迭代 8 个项目。我想将这 8 项存储在属于那一代的数组中:
class Pokedex extends React.Component{
constructor(){
super()
this.state={
pokedex: [
{ index: 1, generation: 1, pokemon: [] },
{ index: 152, generation: 2, pokemon: [] },
{ index: 252, generation: 3, pokemon: [] },
{ index: 387, generation: 4, pokemon: [] },
{ index: 495, generation: 5, pokemon: [] },
{ index: 650, generation: 6, pokemon: [] },
{ index: 722, generation: 7, pokemon: [] },
{ index: 810, generation: 8, pokemon: [] }
]
}
}
fetchPokemon(index){
for(var i=index; i<=index+8; i++){
axios.get(`https://pokeapi.co/api/v2/pokemon/${i}`)
.then((res) => {
return res.data.name;
})
.catch(err => console.log(err));
}
}
componentDidMount(){
this.state.pokedex.forEach(i => {
this.fetchPokemon(i.index)
});
}
render(){
return()
}
}
export default Pokedex
如何使用 setState 将每次 this.fetchPokemon(index)
迭代的结果保存到它所属的 state.pokedex 对象中?
尝试:
UNSAFE_componentWillMount() { // has to be UNSAFE as you are changing state on mount
let pokedexKeys = Object.keys(this.state.pokedex); // getting all keys in a list
pokedexKeys.forEach((pokeKey) => { // looping through keys
this.setState((prev) => ({
pokedex: {
...prev.pokedex, // writing previous state
[pokeKey]: { // overwriting object with current key
...this.state.pokedex[pokeKey], // taking previous values
pokemon: this.fetchPokemon(pokeKey), // fetching data
},
},
}));
});
}
并更改您的状态:
{
pokedex: [
{ index: 1, generation: 1, pokemon: [] },
{ index: 152, generation: 2, pokemon: [] },
....
]
}
收件人:
{
pokedex: { // changing it from list to object
1: {generation: 1, pokemon: [] }, // with index as key
152: {generation: 2, pokemon: [] },
....
}
}
所以这不是最好的方法,但可能有效...
避免不可变数据结构
不可变数据允许直接使用内存引用并且需要更少的过程。
我们在使用不可变数据时遇到一个常见问题,即尝试比较没有相同引用的变量的变化。
如果直接在道具中进行了一些更改,我们不能这样比较:
React.memo(SomeComp, (props, nextProps) => {
if (props.prop1 === nextProps.prop1) {
return true;
}
});
示例:
let neymar = { "name": "Neymar", "score": 1 }
neymar.score = 2
console.log(neymar)
const mbappe = { "name": "mbappe", "score": 0 }
const updateMbappe = {...mbappe, score: 4};
console.log(updateMbappe)
尝试这样的事情:
import React from 'react'
import axios from 'axios'
const pokemonList = [
{ index: 1, generation: 1, pokemon: [] },
{ index: 152, generation: 2, pokemon: [] },
{ index: 252, generation: 3, pokemon: [] },
{ index: 387, generation: 4, pokemon: [] },
{ index: 495, generation: 5, pokemon: [] },
{ index: 650, generation: 6, pokemon: [] },
{ index: 722, generation: 7, pokemon: [] },
{ index: 810, generation: 8, pokemon: [] }
];
const fetchPokemon = (index) => {
const fillPokemonList = [];
for(var i=index; i<=index+8; i++){
axios.get(`https://pokeapi.co/api/v2/pokemon/${i}`)
.then((res) => {
fillPokemonList.push(res.data.name);
})
.catch(err => console.log(err));
}
return fillPokemonList;
}
class Pokedex extends React.Component{
constructor(){
super()
this.state={
pokedex: pokemonList
}
}
componentDidMount(){
this.getPokemons()
}
getPokemons() {
const copyList = this.state.pokedex;
copyList.forEach(i => {
i.pokemon.push(fetchPokemon(i.index))
});
this.setState(copyList)
}
render() {
return()
}
}
export default Pokedex;
无法理解在 React 中使用 setState 挂载组件的最佳实践。我有一个应用程序,returns 每一代口袋妖怪的初始口袋妖怪。每一代都有自己的 axios.get() 方法迭代 8 个项目。我想将这 8 项存储在属于那一代的数组中:
class Pokedex extends React.Component{
constructor(){
super()
this.state={
pokedex: [
{ index: 1, generation: 1, pokemon: [] },
{ index: 152, generation: 2, pokemon: [] },
{ index: 252, generation: 3, pokemon: [] },
{ index: 387, generation: 4, pokemon: [] },
{ index: 495, generation: 5, pokemon: [] },
{ index: 650, generation: 6, pokemon: [] },
{ index: 722, generation: 7, pokemon: [] },
{ index: 810, generation: 8, pokemon: [] }
]
}
}
fetchPokemon(index){
for(var i=index; i<=index+8; i++){
axios.get(`https://pokeapi.co/api/v2/pokemon/${i}`)
.then((res) => {
return res.data.name;
})
.catch(err => console.log(err));
}
}
componentDidMount(){
this.state.pokedex.forEach(i => {
this.fetchPokemon(i.index)
});
}
render(){
return()
}
}
export default Pokedex
如何使用 setState 将每次 this.fetchPokemon(index)
迭代的结果保存到它所属的 state.pokedex 对象中?
尝试:
UNSAFE_componentWillMount() { // has to be UNSAFE as you are changing state on mount
let pokedexKeys = Object.keys(this.state.pokedex); // getting all keys in a list
pokedexKeys.forEach((pokeKey) => { // looping through keys
this.setState((prev) => ({
pokedex: {
...prev.pokedex, // writing previous state
[pokeKey]: { // overwriting object with current key
...this.state.pokedex[pokeKey], // taking previous values
pokemon: this.fetchPokemon(pokeKey), // fetching data
},
},
}));
});
}
并更改您的状态:
{
pokedex: [
{ index: 1, generation: 1, pokemon: [] },
{ index: 152, generation: 2, pokemon: [] },
....
]
}
收件人:
{
pokedex: { // changing it from list to object
1: {generation: 1, pokemon: [] }, // with index as key
152: {generation: 2, pokemon: [] },
....
}
}
所以这不是最好的方法,但可能有效...
避免不可变数据结构
不可变数据允许直接使用内存引用并且需要更少的过程。
我们在使用不可变数据时遇到一个常见问题,即尝试比较没有相同引用的变量的变化。
如果直接在道具中进行了一些更改,我们不能这样比较:
React.memo(SomeComp, (props, nextProps) => {
if (props.prop1 === nextProps.prop1) {
return true;
}
});
示例:
let neymar = { "name": "Neymar", "score": 1 }
neymar.score = 2
console.log(neymar)
const mbappe = { "name": "mbappe", "score": 0 }
const updateMbappe = {...mbappe, score: 4};
console.log(updateMbappe)
尝试这样的事情:
import React from 'react'
import axios from 'axios'
const pokemonList = [
{ index: 1, generation: 1, pokemon: [] },
{ index: 152, generation: 2, pokemon: [] },
{ index: 252, generation: 3, pokemon: [] },
{ index: 387, generation: 4, pokemon: [] },
{ index: 495, generation: 5, pokemon: [] },
{ index: 650, generation: 6, pokemon: [] },
{ index: 722, generation: 7, pokemon: [] },
{ index: 810, generation: 8, pokemon: [] }
];
const fetchPokemon = (index) => {
const fillPokemonList = [];
for(var i=index; i<=index+8; i++){
axios.get(`https://pokeapi.co/api/v2/pokemon/${i}`)
.then((res) => {
fillPokemonList.push(res.data.name);
})
.catch(err => console.log(err));
}
return fillPokemonList;
}
class Pokedex extends React.Component{
constructor(){
super()
this.state={
pokedex: pokemonList
}
}
componentDidMount(){
this.getPokemons()
}
getPokemons() {
const copyList = this.state.pokedex;
copyList.forEach(i => {
i.pokemon.push(fetchPokemon(i.index))
});
this.setState(copyList)
}
render() {
return()
}
}
export default Pokedex;