首页 > 解决方案 > TypeError:无法使用 redux 和 Django Rest 框架读取未定义的属性“映射”来提取数据

问题描述

我已经检查过此类问题的答案,但无法重现该解决方案。

有问题的代码:

AboutUs.js

import React, { useState, useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { Row, Col, Card, Container, Button} from 'react-bootstrap'
import { Link } from 'react-router-dom'
// import Rating from '../components/Rating'
import Loader from '../components/Loader'
import Message from '../components/Message'
import Paginate from '../components/Paginate'
import { listAboutUs } from '../actions/aboutUsActions'

function AboutUs() {
    const dispatch = useDispatch()
    const aboutUsList = useSelector(state => state.aboutUsList)
    const { error, loading, about} = aboutUsList

    
    useEffect(() => {
        dispatch(listAboutUs())

    }, [dispatch])
    return (
        <div>
            {loading ? <Loader />
                : error ? <Message variant='danger'>{error}</Message>
                    :
                    <div>
                       
                        <Container variant='success'>
                    
                            {about.map(item => (
                                <Col key={item._id} sm={12} md={6} lg={4} xl={3}>
                                    
                                    <Card style={{minWidth:'auto', maxWidth:'auto'}}   >
                                    
                                    </Card>
                                    
                                    <Card style={{ width: '18rem' ,  height: '30rem'}} className= "card border-success mb-2 my-0 p-2 rounded">
                                        <Card.Header>ID : {item._id}</Card.Header>
                                        <Card.Body>CardBody</Card.Body>
                                    </Card>

                                </Col>
                            ))}
                        
                       
                        </Container>
                    </div>
                    
            }
        </div>
    )
}

export default AboutUs

相对减速器

import {
    ABOUT_LIST_REQUEST,
    ABOUT_LIST_SUCCESS,
    ABOUT_LIST_FAIL, } from '../constants/aboutConstants'


export const aboutUsListReducer = (state = { about: [] }, action) => {
    switch (action.type) {
        case ABOUT_LIST_REQUEST:
            return { loading: true, about: [] }

        case ABOUT_LIST_SUCCESS:
            return {
                loading: false,
                about: action.payload.about,
            }

        case ABOUT_LIST_FAIL:
            return { loading: false, error: action.payload }

        default:
            return state
    }
}

aboutUsActions.js

import axios from 'axios'
import {
    ABOUT_LIST_REQUEST,
    ABOUT_LIST_SUCCESS,
    ABOUT_LIST_FAIL, } from '../constants/aboutConstants'

export const listAboutUs = () => async (dispatch) => {
    try {
        dispatch({ type: ABOUT_LIST_REQUEST })

        const { data } = await axios.get(`/api/branding/about/`)

        dispatch({
            type: ABOUT_LIST_SUCCESS,
            payload: data
        })

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

store.js

import { createStore, combineReducers, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import { composeWithDevTools } from 'redux-devtools-extension'

import {
    aboutUsListReducer,
    
} from './reducers/aboutUsReducers'

const reducer = combineReducers({
    aboutUsList: aboutUsListReducer,
})

const cartItemsFromStorage = localStorage.getItem('cartItems') ?
    JSON.parse(localStorage.getItem('cartItems')) : []

const userInfoFromStorage = localStorage.getItem('userInfo') ?
    JSON.parse(localStorage.getItem('userInfo')) : null


const shippingAddressFromStorage = localStorage.getItem('shippingAddress') ?
    JSON.parse(localStorage.getItem('shippingAddress')) : {}


const initialState = {
    cart: {
        cartItems: cartItemsFromStorage,
        shippingAddress: shippingAddressFromStorage,
    },
    userLogin: { userInfo: userInfoFromStorage },
    
}

const middleware = [thunk]

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

export default store

商店中还有其他减速器,但包括相关的一个

api endpoint http://localhost:8000/api/branding/about/

我在其他模型中使用了相同的方法从 Django Rest Api 获取数据,它们工作正常,但我不知道这次为什么会发生这种情况。请告诉我我做错了什么或解决此问题的其他相关可能方法。

API工作正常,但我包括views.py

@api_view(['GET'])
def getAboutUs(request):
    about = AboutUs.objects.all()
    serializer = AboutUsSerializer(about, many=True)
    return Response(serializer.data)

完全错误

TypeError: Cannot read property 'map' of undefined
AboutUs
E:/eCommerce_Projects/remote-hospital/frontend/src/screens/AboutUs.js:28
  25 | :
  26 | <div>
  27 |    
> 28 |     <Container variant='success'>
     | ^  29 | 
  30 |         {about.map(item => (
  31 |             <Col key={item._id} sm={12} md={6} lg={4} xl={3}>
View compiled
▶ 24 stack frames were collapsed.
(anonymous function)
E:/eCommerce_Projects/remote-hospital/frontend/src/actions/aboutUsActions.js:13
  10 | 
  11 |        const { data } = await axios.get(`/api/branding/about/`)
  12 | 
> 13 |        dispatch({
     | ^  14 |            type: ABOUT_LIST_SUCCESS,
  15 |            payload: data
  16 |        })
View compiled

标签: reactjsreduxdjango-rest-frameworkreact-reduxreact-hooks

解决方案


在第 30 行的 aboutUs.js 中

尝试做

{Array.isArray(about) && about.map(…)}

简单的解释:您很可能试图映射 sn 未定义的值。这通常是由 http 调用和渲染方法之间的竞争条件引起的

另一种解决方案是将 vslue about 初始化为 sn 数组about = [],并确保 about 的值在组件的整个生命周期中保持为数组

更新:

{loading ? <Loader />
                : error ? <Message variant='danger'>{error}</Message>
                    :
                    <div>
                       
                        <Container variant='success'>
                    
                            {Array.isArray(about) && about.map(item => (. <———————
                                <Col key={item._id} sm={12} md={6} lg={4} xl={3}>
                                    
                                    <Card style={{minWidth:'auto', maxWidth:'auto'}}   >
                                    
                                    </Card>
                                    
                                    <Card style={{ width: '18rem' ,  height: '30rem'}} className= "card border-success mb-2 my-0 p-2 rounded">
                                        <Card.Header>ID : {item._id}</Card.Header>
                                        <Card.Body>CardBody</Card.Body>
                                    </Card>

                                </Col>
                            ))}
                        
                       
                        </Container>
                    </div>
                    
            }

推荐阅读