【问题标题】:React redux state is undefined on first render despite of initlizedState尽管有 initlizedState,但 React redux 状态在第一次渲染时未定义
【发布时间】:2021-11-10 07:28:07
【问题描述】:

Redux 状态在第一次渲染中未定义,我在 reducer 中返回了 initilizedState = {}

store.js

const store = createStore(
    rootReducer,

    compose(
        applyMiddleware(thunk),
        window.devToolsExtension ? window.devToolsExtension() : (f) => f
    )
)

export default store

rootReducer.js

const rootReducer = combineReducers({
    search: searchReducer,
    product: productReducer,
})

export default rootReducer

reducer.js

const initialState = {}
const productReducer = (state = initialState, action) => {
    const { type, payload } = action
    switch (type) {
        case PRODUCTS_ALL:
            console.log('reducer')
            return { ...state, items: payload }
        default:
            return state
    }
}

export default productReducer

action.js

const products = axios.create({
    baseURL: 'http://localhost:8001/api/products',
})
export const allProducts = () => async (dispatch) => {
    console.log('fetching')
    await products.get('/').then((res) => {
        dispatch({
            type: PRODUCTS_ALL,
            payload: res.data,
        })
    })
}

虽然我在提要容器中使用了 connect()

Feed.js

function Feed({ allProducts, product }) {
    const [productItems, setProductItems] = useState()
    const [loading, setLoading] = useState(false)

    React.useEffect(() => {
        allProducts()
        console.log(product)
    }, [])

    return (
        
                            
            <div className='feed__content'>
                {loading ? (
                    <Loader
                        type='Oval'
                        color='#212121'
                        height={100}
                        width={100}
                    />
                ) : (
                    <div className='feed__products'>
                        <div className='feed__productsList'>
                             {product.map((product) => {
                                return (
                                    <Product
                                        name={product.name}
                                        image={product.image}
                                        price={product.price}
                                    />
                                )
                            })} 
                        </div>
                        
                    </div>
                )}

        </div>
    )
}

const mapStateToProps = (state) => ({
    product: state.product.items,
})
const mapDispatchToProps = (dispatch) => {
    return {
        allProducts: () => dispatch(allProducts()),
    }
}
export default connect(mapStateToProps, mapDispatchToProps)(Feed)

如果您查看控制台上的数据,您将看到 undefined 但如果我添加 useEffect 依赖项,它将创建一个循环,其中第一个是未定义的,其余的是我想要的数据。 因为这个问题,当我想用​​ map 渲染产品时,它会抛出一个错误,说 can't map undefiend 。

我该如何解决这个问题

【问题讨论】:

  • 你真的定义了初始状态吗? (state = initialState, action)
  • @Nectos 是的,我添加了 initialState
  • 你能告诉我们你是如何初始化 redux 存储的吗?您的 createStore 函数调用是什么样的?您是否添加了预加载状态?
  • @Andrew 我添加了我的 store.js 文件先生我应该怎么做
  • 好吧,如果我理解正确的话,第一次渲染实际上比状态变化发生得更快,导致 undefined 部分,所以第二次渲染它将填充数据(product?.map 也可以提供帮助)。您可以添加保护子句以防止在没有数据时进行渲染。因为它在reducer store,你实际上可以使用useSelector。我也看不到loading 被设置为true 的位置。

标签: javascript reactjs react-redux axios


【解决方案1】:

您尝试在 redux 中执行异步操作的代码的 A/c。为此,您应该使用 redux-saga 或 redux-thunk。

但是您可以通过以下方式实现输出,而不使用 redux-saga 或 thunk。

按以下方式修改您的代码:

Feed.js

function Feed({ allProducts, product }) {
  // Set loading to true inititally
  const [loading, setLoading] = useState(true);

  React.useEffect(() => {
    // Make your api call here once its complete and you get a res, 
    // dispatch the referred action with response as payload.
    (async () => {
        const products = axios.create({
            baseURL: "http://localhost:8001/api/products",
          });
        const {data} = await products.get("/");
        allProducts(data);
    })()
  // This call is only made when you load it for the first time, if it 
  // depends 
  // on something add that dependencies in the dependency array of // 
  // useEffect.
  }, []);

  // once store is updated with the passed payload. Set loading to 
  // false.
  React.useEffect(() => {
    if(product){
        setLoading(false);
    }
  }, [product])

  return (
    <div className="feed__content">
      {loading ? (
        <Loader type="Oval" color="#212121" height={100} width={100} />
      ) : (
        <div className="feed__products">
          <div className="feed__productsList">
            {product.map((product) => {
              return (
                <Product
                  name={product.name}
                  image={product.image}
                  price={product.price}
                />
              );
            })}
          </div>
        </div>
      )}
    </div>
  );
}


const mapStateToProps = ({product}) => ({
  product: product?.items,
});

// here we have a payload to pass
const mapDispatchToProps = (dispatch) => {
  return {
    allProducts: (payload) => dispatch(allProducts(payload)),
  };
};
export default connect(mapStateToProps, mapDispatchToProps)(Feed);

动作

export const allProducts = (payload) => ({   
      type: "PRODUCTS_ALL",
      payload,
});

减速器

const productReducer = (state = initialState, action) => {
    const { type, payload } = action
    switch (type) {
        case "PRODUCTS_ALL":
            return { ...state, items: payload }
        default:
            return state
    }
}

导出默认productReducer

【讨论】:

    【解决方案2】:

    Feed.js 中,您没有获得完整的状态片段。您正在尝试访问里面的密钥item

    const mapStateToProps = (state) => ({
        product: state.product.items,
    })
    

    更改您的 initialState 以包含该密钥,您的代码应该没问题

    const initialState = {
      items: []
    }
    

    【讨论】:

      【解决方案3】:

      Joel Jaimon 代码运行良好。

      在我的代码中我添加了

      const initialState = {
        items: []
      }
      

      根据 @Andrew 和 product?.map,所以我的代码现在运行良好。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-01-14
        • 2022-10-08
        • 2021-02-09
        • 2021-11-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-31
        相关资源
        最近更新 更多