如何使用api的数据初始化状态

Ndx*_*Ndx 2 api reactjs redux axios

我正在创建一个从 api (pokeapi.co) 获取数据的 React/Redux 应用程序。我使用axios. 当我在 react 组件上显示数据时,会导致数据为undefined. 经过一番挖掘,我发现我的状态首先返回初始状态,即空对象,然后返回 api 数据。但它不会在反应中显示。我是 React 的新手,所以我猜它与 axios 异步功能有关。您如何使用 api 的初始数据设置状态或等待呈现数据直到状态具有 api 的数据?

这是减速机

function pokemonReducer(state={}, action) {
    switch (action.type) {
        case pokemonsActions.GET_POKEMON_SUCCESS:
            {
                return  {...state, data: action.payload.data}
            }

        default:
            {
                return state;
            }
    }
}

export default pokemonReducer
Run Code Online (Sandbox Code Playgroud)

这是动作

export const GET_POKEMON_SUCCESS = 'GET_POKEMON_SUCCESS'
export const GET_POKEMON_ERROR = 'GET_POKEMON_ERROR'

function getPokemonSuccess(response) {
    return {
        type: GET_POKEMON_SUCCESS,
        payload: response
    }

}

function getPokemonError(err) {
    return {
        type: GET_POKEMON_ERROR,
        payload: err
    }
}
export function getPokemon() {
    return (disp,getState) => 
             {
                return pokeAPI.getPokeAPI()
                              .then((response) => { disp(getPokemonSuccess(response))})
                              .catch((err)=> disp(getPokemonError(err)))

             }
}
Run Code Online (Sandbox Code Playgroud)

店铺

const loggerMiddleware = createLogger()
const middleWare= applyMiddleware(thunkMiddleware,loggerMiddleware);

const store = createStore(rootReducer,preloadedState,
 compose(middleWare, typeof window === 'object' && typeof window.devToolsExtension !== 'undefined'
  ? window.devToolsExtension() : (f) => f
))


const preloadedState=store.dispatch(pokemonActions.getPokemon())

export default store
Run Code Online (Sandbox Code Playgroud)

在 React 组件中

function mapStateToProps(state) {
  return {
    pokemons:state.pokemons
  }
}

    class PokemonAbility extends React.Component {

        render(){
            return (
                <div>
                <div className="header">
                  <h1>Fetch Poke Api with axios</h1>
                 </div>
                    <main>
                    <h3> Display pokemons abilities </h3>
                        <p>{this.props.pokemons.data.count}</p>
                    </main>
                </div>
                )
        }
    }


    export default connect(
      mapStateToProps
    )(PokemonAbility)
Run Code Online (Sandbox Code Playgroud)

Api 数据示例

{
    "count": 292,
    "previous": null,
    "results": [
        {
            "url": "https://pokeapi.co/api/v2/ability/1/",
            "name": "stench"
        },
        {
            "url": "https://pokeapi.co/api/v2/ability/2/",
            "name": "drizzle"
        },
        {
            "url": "https://pokeapi.co/api/v2/ability/3/",
            "name": "speed-boost"
        }
    ],
    "next": "https://pokeapi.co/api/v2/ability/?limit=20&offset=20"
}
Run Code Online (Sandbox Code Playgroud)

And*_*Ray 5

您在加载数据之前渲染组件。有很多策略可以解决这个问题。没有特别的顺序,这里有一些例子:

1. 使渲染器短路

如果数据不存在,您可以通过返回加载消息来短路渲染:

function mapStateToProps(state) {
    return {
        pokemons:state.pokemons
    }
}
class PokemonAbility extends React.Component {
    render(){
        if (!this.props.pokemons.data) {
            return (
                <div>Loading...</div>
            );
        }
        return (
            <div>
                <div className="header">
                    <h1>Fetch Poke Api with axios</h1>
                </div>
                <main>
                    <h3> Display pokemons abilities </h3>
                    <p>{this.props.pokemons.data.count}</p>
                </main>
            </div>
        );
    }
}

export default connect(mapStateToProps)(PokemonAbility);
Run Code Online (Sandbox Code Playgroud)

2. 将数据校验提升到父组件

您可以将 移动mapStateToProps到更高的组件中,或者抽象出视图组件,并仅在数据准备好时才渲染视图:

function mapStateToProps(state) {
    return {
        pokemons:state.pokemons
    }
}
class SomeHigherComponent extends React.Component {
    render(){
        return (
            this.props.pokemons.data ?
                <PokemonAbility pokemons={this.props.pokemons} /> :
                <div>Loading...</div>
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

3. 高阶元件数据检查

您可以将组件包装在“高阶组件”(一个接受组件类并返回组件类的函数)中,以在渲染之前检查该道具是否存在:

function EnsurePokemon(ChildComponent) {
    return class PokemonEnsureWrapper extends React.Component {
        render() {
            return (
                this.props.pokemons.data ?
                    <ChildComponent {...this.props} /> :
                    <div>Loading...</div>
            );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

export default connect(
    mapStateToProps
)(EnsurePokemon(PokemonAbility))
Run Code Online (Sandbox Code Playgroud)

你可以在这个EnsurePokemonHOC 中包装任何子组件,以确保它在数据加载之前不会呈现。