Answer a question

So im following this tutorial and im struggling with the following step. Redux was introduced and it not working. I googled the error that I found in the developer Tool and I still couldn't fix the error by trying many proposed solutions. The error is in HomeScreen in line 25 (products.map) My code:

HomeScreen.js:

import React, {useState, useEffect} from 'react'
import {Row, Col} from 'react-bootstrap'
import Product from '../components/Product'
import { useDispatch, useSelector} from 'react-redux'
import {listProducts} from '../actions/productActions'


function HomeScreen() {

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

    useEffect(() =>{
        dispatch(listProducts())
    },[dispatch])
    
  return (
    
        <div>
            <h1>Latest Products</h1>
            {loading ? <h2>Loading..</h2>
                : error ? <h3>{error}</h3>
                :
                <Row>
                {products.map(product => (
                    <Col key={product._id} sm={8} md={6} lg={4} xl={2}>
                        <Product product={product} />
                    </Col>
                ))}
                </Row>
            }
            
        </div>
    
  )
}

store.js:

import { legacy_createStore as createStore, combineReducers, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import { composeWithDevTools } from 'redux-devtools-extension'
import {productListReducer} from './reducers/productReducers'


const reducer = combineReducers({
    productList: productListReducer,
})
const initialState = {}
const middleware = [thunk]
const store = createStore(reducer, initialState, 
    composeWithDevTools(applyMiddleware(...middleware)))

export default store

productActions.js:

import axios from 'axios'
import {PRODUCT_LIST_REQUEST,PRODUCT_LIST_SUCCESS,PRODUCT_LIST_FAIL} from '../constants/productConstants'

export const listProducts = () =>  async(dispatch) => {
    try {
        dispatch({type: PRODUCT_LIST_REQUEST})

        const {data} =  await axios.get('/api/products/')

        dispatch({
            type: PRODUCT_LIST_SUCCESS,
            payload: data
        })
    } catch (error) {
        dispatch({
            type: PRODUCT_LIST_FAIL,
            payload: error.response && error.response.data.message
            ? error.response.data.message
            : error.message, 
        })
    }
}

productReducers.js

import {
    PRODUCT_LIST_REQUEST,
    PRODUCT_LIST_SUCCESS,
    PRODUCT_LIST_FAIL
} from '../constants/productConstants'


export const productListReducer = (state={products:[]},action) => {
    switch(action.type){
        case PRODUCT_LIST_REQUEST:
            return {loading:true, product:[]}

        case PRODUCT_LIST_SUCCESS:
            return {loading:false, product:action.payload}

        case PRODUCT_LIST_FAIL:
            return {loading:false, error: action.payload}
        
        default:
            return state
    }
}

Answers

You should consistently name the state. The state is initially named products, but all the case reducers replace it with product. Don't forget to also always shallow copy the previous state object into the next state object.

export const productListReducer = (state={ products: [] }, action) => {
  switch(action.type) {
    case PRODUCT_LIST_REQUEST:
      return {
        ...state,
        loading: true,
        products: [],
      };

    case PRODUCT_LIST_SUCCESS:
      return {
        ...state,
        loading: false,
        products: action.payload,
        error: null,
      };

    case PRODUCT_LIST_FAIL:
      return {
        ...state,
        loading: false,
        error: action.payload,
      };
    
    default:
      return state;
  }
}
Logo

React社区为您提供最前沿的新闻资讯和知识内容

更多推荐