TypeError: products.map is not a function. Most likely Problems are in redux
TypeError: products.map is not a function. Most likely Problems are in redux
如何解决这个问题?我在此处附上了所有相关的代码片段。当我尝试在主屏幕上呈现产品时,出现此错误,当我打开此项目时,它显示加载几秒钟,然后显示此错误。如何修复此错误?
import React, { useEffect} from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { Row, Col } from 'react-bootstrap'
import Product from '../components/Product'
import { listProducts } from '../actions/productActions.js'
import Message from '../components/Message'
import Loader from '../components/Loader'
const HomeScreen = () => {
const dispatch = useDispatch()
const productList = useSelector((state) => state.productList);
const { loading, error, products} = productList;
useEffect(() => {
dispatch(listProducts())
}, [dispatch])
return (
<>
<h1>All Products</h1>
{loading ? (
<Loader />
) : error ? (
<Message variant='danger'>{error}</ Message>
) : (
<Row>
{products.map((product) => (
<Col sm={12} md={6} lg={4} xl={3} key={product._id}>
<Product product={product} />
</Col>
))}
</Row>
)}
</>
)
}
export default HomeScreen
这里是redux的productAction页面
import {PRODUCT_LIST_REQUEST, PRODUCT_LIST_SUCCESS, PRODUCT_LIST_FAIL,
PRODUCT_DETAILS_REQUEST, PRODUCT_DETAILS_SUCCESS, PRODUCT_DETAILS_FAIL} from '../constants/productConstants'
import axios from 'axios'
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
})
}
}
export const listProductDetails = (id) => async (dispatch) => {
try {
dispatch({ type: PRODUCT_DETAILS_REQUEST })
const { data } = await axios.get(`/api/products/${id}`)
dispatch({
type: PRODUCT_DETAILS_SUCCESS,
payload: data,
})
} catch (error) {
dispatch({
type: PRODUCT_DETAILS_FAIL,
payload:
error.response && error.response.data.message
? error.response.data.message
: error.message,
})
}
}
productReducers 页面:
import {PRODUCT_LIST_REQUEST, PRODUCT_LIST_SUCCESS, PRODUCT_LIST_FAIL,
PRODUCT_DETAILS_REQUEST, PRODUCT_DETAILS_SUCCESS, PRODUCT_DETAILS_FAIL} from '../constants/productConstants'
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
}
}
export const productDetailsReducer = (
state = { product: { reviews: [] } },
action
) => {
switch (action.type) {
case PRODUCT_DETAILS_REQUEST:
return { loading: true, ...state }
case PRODUCT_DETAILS_SUCCESS:
return { loading: false, product: action.payload }
case PRODUCT_DETAILS_FAIL:
return { loading: false, error: action.payload }
default:
return state
}
}
首先看看你的API是否正常工作。
如果它工作正常,即使你遇到这个错误,那么问题出在你更新 redux 存储的方式上。
这里的 products 是来自 productList 的元素。您正在更改对象的 属性,但从 React 的角度来看,对象本身似乎没有发生变化。
检查你的 reducer 逻辑,如果你正在更新存储值,就这样做
initialState = { loading, error, products: [] }
......
......
return {
...state,
products: [...fetched products]
}
这 3 个点 (...) 确保您创建了一个新对象。在 redux 上,你必须始终创建一个新对象,而不仅仅是更新状态。
- 使用变量时,始终首先验证您要使用的变量及其 属性 是否存在。在您的情况下,您直接使用 products.map,这会破坏前端。首先检查产品是否真的是一个列表,然后使用 products.map。这样,即使产品值未定义,您的前端也不会崩溃。
我通过将 action.payload.products
添加到 productReducers 页面解决了这个问题。
固定代码在这里:
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.products}
case PRODUCT_LIST_FAIL:
return { loading: false, error: action.payload}
default:
return state
}
}
如何解决这个问题?我在此处附上了所有相关的代码片段。当我尝试在主屏幕上呈现产品时,出现此错误,当我打开此项目时,它显示加载几秒钟,然后显示此错误。如何修复此错误?
import React, { useEffect} from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { Row, Col } from 'react-bootstrap'
import Product from '../components/Product'
import { listProducts } from '../actions/productActions.js'
import Message from '../components/Message'
import Loader from '../components/Loader'
const HomeScreen = () => {
const dispatch = useDispatch()
const productList = useSelector((state) => state.productList);
const { loading, error, products} = productList;
useEffect(() => {
dispatch(listProducts())
}, [dispatch])
return (
<>
<h1>All Products</h1>
{loading ? (
<Loader />
) : error ? (
<Message variant='danger'>{error}</ Message>
) : (
<Row>
{products.map((product) => (
<Col sm={12} md={6} lg={4} xl={3} key={product._id}>
<Product product={product} />
</Col>
))}
</Row>
)}
</>
)
}
export default HomeScreen
这里是redux的productAction页面
import {PRODUCT_LIST_REQUEST, PRODUCT_LIST_SUCCESS, PRODUCT_LIST_FAIL,
PRODUCT_DETAILS_REQUEST, PRODUCT_DETAILS_SUCCESS, PRODUCT_DETAILS_FAIL} from '../constants/productConstants'
import axios from 'axios'
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
})
}
}
export const listProductDetails = (id) => async (dispatch) => {
try {
dispatch({ type: PRODUCT_DETAILS_REQUEST })
const { data } = await axios.get(`/api/products/${id}`)
dispatch({
type: PRODUCT_DETAILS_SUCCESS,
payload: data,
})
} catch (error) {
dispatch({
type: PRODUCT_DETAILS_FAIL,
payload:
error.response && error.response.data.message
? error.response.data.message
: error.message,
})
}
}
productReducers 页面:
import {PRODUCT_LIST_REQUEST, PRODUCT_LIST_SUCCESS, PRODUCT_LIST_FAIL,
PRODUCT_DETAILS_REQUEST, PRODUCT_DETAILS_SUCCESS, PRODUCT_DETAILS_FAIL} from '../constants/productConstants'
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
}
}
export const productDetailsReducer = (
state = { product: { reviews: [] } },
action
) => {
switch (action.type) {
case PRODUCT_DETAILS_REQUEST:
return { loading: true, ...state }
case PRODUCT_DETAILS_SUCCESS:
return { loading: false, product: action.payload }
case PRODUCT_DETAILS_FAIL:
return { loading: false, error: action.payload }
default:
return state
}
}
首先看看你的API是否正常工作。
如果它工作正常,即使你遇到这个错误,那么问题出在你更新 redux 存储的方式上。 这里的 products 是来自 productList 的元素。您正在更改对象的 属性,但从 React 的角度来看,对象本身似乎没有发生变化。
检查你的 reducer 逻辑,如果你正在更新存储值,就这样做
initialState = { loading, error, products: [] }
......
......
return {
...state,
products: [...fetched products]
}
这 3 个点 (...) 确保您创建了一个新对象。在 redux 上,你必须始终创建一个新对象,而不仅仅是更新状态。
- 使用变量时,始终首先验证您要使用的变量及其 属性 是否存在。在您的情况下,您直接使用 products.map,这会破坏前端。首先检查产品是否真的是一个列表,然后使用 products.map。这样,即使产品值未定义,您的前端也不会崩溃。
我通过将 action.payload.products
添加到 productReducers 页面解决了这个问题。
固定代码在这里:
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.products}
case PRODUCT_LIST_FAIL:
return { loading: false, error: action.payload}
default:
return state
}
}