如何正确使用异步 React-Redux 状态

How to use async React-Redux state properly

我通过 react-redux 从 api 中获取了一些数据。我的问题是,因为它是异步的,所以我必须等待状态更新其初始值才能在应用程序中使用它们。例如我必须使用

products && products.length && products[n].img

当我尝试访问获取的数据时,语法不会出现未定义的错误。但是当我在第一次渲染时使用它们就像

products[n].img

应用程序给出了 undefined ,因为它应该是因为 redux 异步获取数据。我怎样才能绕过这些步骤,以便立即使用我想要的状态?

反应代码

import React, { useEffect } from "react";
import {useDispatch, useSelector} from 'react-redux'
import { listPoduct } from "../actions/productActions";

const Examples = () => {

    const dispatch = useDispatch()

    const productList = useSelector(state => state.productList)
    const {loading, error, products} = productList

    useEffect(()=>{
        dispatch(listPoduct())
    },[dispatch])

    console.log(products && products.length && products[0].img)

    return(
        <div>
          ...
        </div>
    )
}

export default Examples

动作

export function listPoduct() {
    return (dispatch) => {
        const baseUrl = "/api/images"
        fetch(`${baseUrl}`)
            .then(res => res.json())
            .then(res => {
                dispatch({
                    type: PRODUCT_LIST_SUCCESS,
                    payload: res
                })
            })
    }
}

减速机

export const productListReducer = (state = { products: [] }, action) => {
    switch (action.type) {
        case PRODUCT_LIST_REQUEST:
            return {loading:true, products:[]}
        case PRODUCT_LIST_SUCCESS:
            return {loading:false, products: action.payload}
        case PRODUCT_LIST_FAIL:
            return {loading:false, error: action.payload}
        default:
            return state
    }
}

商店

import {createStore, combineReducers, applyMiddleware} from 'redux' 
import thunk from 'redux-thunk'
import {composeWithDevTools} from 'redux-devtools-extension' 
import {productListReducer, productDetailsReducer} from './reducers/productReducer'

const reducer = combineReducers({
    productList: productListReducer,
    productDetails: productDetailsReducer
})

const initialState = {}

const middleware = [thunk]

const store = createStore(
    reducer,
    initialState,
    composeWithDevTools(applyMiddleware(...middleware))
  )

export default store 

简短的回答是你不能。可悲的是。 您的请求是异步的,因此没有立即可用的数据。 在您的特定情况下,我的建议是有条件地呈现某种 spinner-loader(如果 loading 设置为 true)并且仅呈现加载程序。 在这种情况下,如果你将 loading 设置为 true,你将不会到达真正可以读取数据的地方(你会 render-and-return 之前)。一旦 loading 切换回 false,您现在可以在请求完成且数据位于正确位置时安全地显示数据。

这同样适用于失败状态(因为如果请求失败也没有可用数据)。

这是您修改后的代码(作为示例):

const Examples = () => {

    const dispatch = useDispatch()

    const productList = useSelector(state => state.productList)
    const {loading, error, products} = productList

    useEffect(()=>{
        dispatch(listPoduct())
    },[dispatch]);

    if (loading) {
        return (<div>Loading...</div>);
    }

    if (error) {
        return (<div>Error: {error}</div>);
    }

    console.log(products && products.length && products[0].img)

    return(
        <div>
          ...
        </div>
    )
}