在 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;