TypeError: Cannot destructure property 'error' of 'panelMembersList' as it is undefined
TypeError: Cannot destructure property 'error' of 'panelMembersList' as it is undefined
我正在尝试使用 redux
和 axios
从 Django REST API
服务器加载数据,我在其他屏幕(如产品、博客帖子)中使用的方法类似,它们工作正常,现在我需要从 api
加载另一个模型,但我不确定为什么会出现此错误...
TypeError: Cannot destructure property 'error' of 'panelMembersList' as it is undefined.
有问题的代码
panelMembersList.js
import { useState, useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { Row, Col, Card, Container, Button} from 'react-bootstrap'
// import PanelMember from '../components/PanelMember'
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 { listPanelMembers } from '../actions/panelMemberActions'
function PanelListScreen({history}) {
const dispatch = useDispatch()
const panelMembersList = useSelector(state => state.panelMembersList)
const {error, loading, allPanelMembers, page, pages } = panelMembersList
let keyword = history.location.search
useEffect(() => {
dispatch(listPanelMembers(keyword))
}, [dispatch, keyword])
return (
<div>
<h3>Our Panel Members</h3>
{loading ? <Loader />
: error ? <Message variant='danger'>{error}</Message>
:
<div>
<Container variant='success'>
<Row>
{allPanelMembers.map(allPanelMembers => (
<Col key={allPanelMembers._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>Joined Date : {allPanelMembers.createdAt}</Card.Header>
<Link to={`/panel/${allPanelMembers._id}`}>
<Card.Img className='mb-0 my-0 p-0' src={allPanelMembers.image} />
</Link>
<Card.Body>
<Link to={`/panel/${allPanelMembers._id}`}>
<Card.Title as="h5"><strong>{allPanelMembers.name}</strong></Card.Title>
</Link>
<Card.Text as="div">
<div className="my-0">
<Rating value={allPanelMembers.rating} text={`${allPanelMembers.numReviews} reviews`} color={'#f8e825'} />
</div>
</Card.Text>
<Link to={`/panel/${allPanelMembers._id}`}><Button variant="btn btn-outline-success">
Read More </Button></Link>
</Card.Body>
</Card>
</Col>
))}
</Row>
<Paginate page={page} pages={pages} keyword={keyword} />
</Container>
</div>
}
</div>
)
}
export default PanelListScreen
当我加载此屏幕时出现以下错误
12 | function PanelListScreen({history}) {
13 | const dispatch = useDispatch()
14 | const panelMembersList = useSelector(state => state.panelMembersList)
> 15 | const {error, loading, allPanelMembers, page, pages } = panelMembersList
16 |
17 | let keyword = history.location.search
18 | useEffect(() => {
提示错误未定义,能否帮忙解决一下。
store.js
import { createStore, combineReducers, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import { composeWithDevTools } from 'redux-devtools-extension'
import {
productListReducer,
productDetailsReducer,
productDeleteReducer,
productCreateReducer,
productUpdateReducer,
productReviewCreateReducer,
productTopRatedReducer,
} from './reducers/productReducers'
import {
panelMemberListReducer,
panelMemberDetailsReducer,
panelMemberReviewCreateReducer,
} from './reducers/panelMemberReducers'
import {
blogPostListReducer,
blogPostDetailsReducer,
blogPostReviewCreateReducer,
} from './reducers/blogReducers'
import { cartReducer } from './reducers/cartReducers'
import {
userLoginReducer,
userRegisterReducer,
userDetailsReducer,
userUpdateProfileReducer,
userListReducer,
userDeleteReducer,
userUpdateReducer,
} from './reducers/userReducers'
import {
orderCreateReducer,
orderDetailsReducer,
orderPayReducer,
orderListMyReducer,
orderListReducer,
orderDeliverReducer,
} from './reducers/orderReducers'
import {
messageListReducer,
messageDetailsReducer,
} from './reducers/messageReducers'
const reducer = combineReducers({
productList: productListReducer,
productDetails: productDetailsReducer,
productDelete: productDeleteReducer,
productCreate: productCreateReducer,
productUpdate: productUpdateReducer,
productReviewCreate: productReviewCreateReducer,
productTopRated: productTopRatedReducer,
panelMemberList: panelMemberListReducer,
panelMemberDetail: panelMemberDetailsReducer,
panelMemberReviewCreate: panelMemberReviewCreateReducer,
cart: cartReducer,
userLogin: userLoginReducer,
userRegister: userRegisterReducer,
userDetails: userDetailsReducer,
userUpdateProfile: userUpdateProfileReducer,
userList: userListReducer,
userDelete: userDeleteReducer,
userUpdate: userUpdateReducer,
orderCreate: orderCreateReducer,
orderDetails: orderDetailsReducer,
orderPay: orderPayReducer,
orderListMy: orderListMyReducer,
orderList: orderListReducer,
orderDeliver: orderDeliverReducer,
blogPostList: blogPostListReducer,
blogPostDetails: blogPostDetailsReducer,
blogPostReviewCreate: blogPostReviewCreateReducer,
listMessages: messageListReducer,
})
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
操作
export const listPanelMembers = (keyword = '') => async (dispatch) => {
try {
dispatch({ type: PANEL_LIST_REQUEST })
const { data } = await axios.get(`/api/panel${keyword}`)
dispatch({
type: PANEL_LIST_SUCCESS,
payload: data
})
} catch (error) {
dispatch({
type: PANEL_LIST_FAIL,
payload: error.response && error.response.data.detail
? error.response.data.detail
: error.message,
})
}
}
减速机
export const panelMemberListReducer = (state = { allPanelMembers: [] }, action) => {
switch (action.type) {
case PANEL_LIST_REQUEST:
return { loading: true, allPanelMembers: [] }
case PANEL_LIST_SUCCESS:
return {
loading: false,
allPanelMembers: action.payload.allPanelMembers,
page: action.payload.page,
pages: action.payload.pages
}
case PANEL_LIST_FAIL:
return { loading: false, error: action.payload }
default:
return state
}
}
api终点
http://localhost:8000/api/panel/
在 useSelector 挂钩数据之前访问该值 returns 数据或您的 redux 存储中未定义主要对象。你可以做的是检查这个对象是否存在然后 deconstruct
示例:
const panelMembersList = useSelector(state => state.panelMembersList)
const [panelData, updatePanelData] = useState({
error: '',
loading: false,
allPanelMembers: [],
page: 0,
pages: 0
});
useEffect(() => {
if(panelMembersList) updatePanelData(panelMembersList)
}, [panelMembersList])
或者用默认数据填充 redux 存储中的对象,以防止被识别为未定义
const initialState = {
panelMembersList: {
error: '',
loading: false,
allPanelMembers: [],
page: 0,
pages: 0
}
}
希望我的回答能帮到您解决问题
我想post回答我做错了什么,基本上是在我在端点使用allPanelMembers
访问数据之前,每次我用同样的方法看到我的其他端点时工作正常,但有一个不同之处,我没有在那里使用驼峰命名法,这导致我更改了 django
端的变量,这可能会有所帮助。然后我将 allPanelMembers
更改为 members
没有骆驼案例。这解决了这个问题。曾经有人告诉我,如果我们在前端使用 React,那么在后端使用驼峰命名法,但现在我知道这是不正确的。
正确代码:
#views.py
@api_view(['GET'])
def getAllPanelMember(request):
query = request.query_params.get('keyword')
if query == None:
query = ''
#originaly this variable was named allPanelMembers
members = PanelMember.objects.filter(
name__icontains=query).order_by('-createdAt')
page = request.query_params.get('page')
paginator = Paginator(members, 8)
try:
members = paginator.page(page)
except PageNotAnInteger:
members = paginator.page(1)
except EmptyPage:
members = paginator.page(paginator.num_pages)
if page == None:
page = 1
page = int(page)
#print('Page:', page) If you want to see in termnial
serializer = PanelMemberSerializer(members, many=True)
return Response({'members': serializer.data, 'page': page, 'pages': paginator.num_pages})
前端
import React, { useState, useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { Row, Col, Card, Image, ListGroup, Container } from 'react-bootstrap'
// import PanelMember from '../components/PanelMember'
import Loader from '../components/Loader'
import Message from '../components/Message'
import Paginate from '../components/Paginate'
import { panelMemberList } from '../actions/panelActions'
function PanelListScreen({ history }) {
const dispatch = useDispatch()
const panelList = useSelector(state => state.panelList)
const { error, loading, members, page, pages } = panelList
let keyword = history.location.search
useEffect(() => {
dispatch(panelMemberList(keyword))
}, [dispatch, keyword])
return (
<div>
<h1>Panel</h1>
{loading ? <Loader /> : error ? <Message variant='danger'>{error}</Message> : <div>
<Container>
<Row>
{
members.map(item=>(
<Col key={item._id} sm={12} md={6} lg={4} xl={3}>
<Card.Header>By : {item.name}</Card.Header>
</Col>
))
}</Row></Container></div>}
<Paginate page={page} pages={pages} keyword={keyword} />
</div>
)
}
export default PanelListScreen
我正在尝试使用 redux
和 axios
从 Django REST API
服务器加载数据,我在其他屏幕(如产品、博客帖子)中使用的方法类似,它们工作正常,现在我需要从 api
加载另一个模型,但我不确定为什么会出现此错误...
TypeError: Cannot destructure property 'error' of 'panelMembersList' as it is undefined.
有问题的代码
panelMembersList.js
import { useState, useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { Row, Col, Card, Container, Button} from 'react-bootstrap'
// import PanelMember from '../components/PanelMember'
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 { listPanelMembers } from '../actions/panelMemberActions'
function PanelListScreen({history}) {
const dispatch = useDispatch()
const panelMembersList = useSelector(state => state.panelMembersList)
const {error, loading, allPanelMembers, page, pages } = panelMembersList
let keyword = history.location.search
useEffect(() => {
dispatch(listPanelMembers(keyword))
}, [dispatch, keyword])
return (
<div>
<h3>Our Panel Members</h3>
{loading ? <Loader />
: error ? <Message variant='danger'>{error}</Message>
:
<div>
<Container variant='success'>
<Row>
{allPanelMembers.map(allPanelMembers => (
<Col key={allPanelMembers._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>Joined Date : {allPanelMembers.createdAt}</Card.Header>
<Link to={`/panel/${allPanelMembers._id}`}>
<Card.Img className='mb-0 my-0 p-0' src={allPanelMembers.image} />
</Link>
<Card.Body>
<Link to={`/panel/${allPanelMembers._id}`}>
<Card.Title as="h5"><strong>{allPanelMembers.name}</strong></Card.Title>
</Link>
<Card.Text as="div">
<div className="my-0">
<Rating value={allPanelMembers.rating} text={`${allPanelMembers.numReviews} reviews`} color={'#f8e825'} />
</div>
</Card.Text>
<Link to={`/panel/${allPanelMembers._id}`}><Button variant="btn btn-outline-success">
Read More </Button></Link>
</Card.Body>
</Card>
</Col>
))}
</Row>
<Paginate page={page} pages={pages} keyword={keyword} />
</Container>
</div>
}
</div>
)
}
export default PanelListScreen
当我加载此屏幕时出现以下错误
12 | function PanelListScreen({history}) {
13 | const dispatch = useDispatch()
14 | const panelMembersList = useSelector(state => state.panelMembersList)
> 15 | const {error, loading, allPanelMembers, page, pages } = panelMembersList
16 |
17 | let keyword = history.location.search
18 | useEffect(() => {
提示错误未定义,能否帮忙解决一下。
store.js
import { createStore, combineReducers, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import { composeWithDevTools } from 'redux-devtools-extension'
import {
productListReducer,
productDetailsReducer,
productDeleteReducer,
productCreateReducer,
productUpdateReducer,
productReviewCreateReducer,
productTopRatedReducer,
} from './reducers/productReducers'
import {
panelMemberListReducer,
panelMemberDetailsReducer,
panelMemberReviewCreateReducer,
} from './reducers/panelMemberReducers'
import {
blogPostListReducer,
blogPostDetailsReducer,
blogPostReviewCreateReducer,
} from './reducers/blogReducers'
import { cartReducer } from './reducers/cartReducers'
import {
userLoginReducer,
userRegisterReducer,
userDetailsReducer,
userUpdateProfileReducer,
userListReducer,
userDeleteReducer,
userUpdateReducer,
} from './reducers/userReducers'
import {
orderCreateReducer,
orderDetailsReducer,
orderPayReducer,
orderListMyReducer,
orderListReducer,
orderDeliverReducer,
} from './reducers/orderReducers'
import {
messageListReducer,
messageDetailsReducer,
} from './reducers/messageReducers'
const reducer = combineReducers({
productList: productListReducer,
productDetails: productDetailsReducer,
productDelete: productDeleteReducer,
productCreate: productCreateReducer,
productUpdate: productUpdateReducer,
productReviewCreate: productReviewCreateReducer,
productTopRated: productTopRatedReducer,
panelMemberList: panelMemberListReducer,
panelMemberDetail: panelMemberDetailsReducer,
panelMemberReviewCreate: panelMemberReviewCreateReducer,
cart: cartReducer,
userLogin: userLoginReducer,
userRegister: userRegisterReducer,
userDetails: userDetailsReducer,
userUpdateProfile: userUpdateProfileReducer,
userList: userListReducer,
userDelete: userDeleteReducer,
userUpdate: userUpdateReducer,
orderCreate: orderCreateReducer,
orderDetails: orderDetailsReducer,
orderPay: orderPayReducer,
orderListMy: orderListMyReducer,
orderList: orderListReducer,
orderDeliver: orderDeliverReducer,
blogPostList: blogPostListReducer,
blogPostDetails: blogPostDetailsReducer,
blogPostReviewCreate: blogPostReviewCreateReducer,
listMessages: messageListReducer,
})
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
操作
export const listPanelMembers = (keyword = '') => async (dispatch) => {
try {
dispatch({ type: PANEL_LIST_REQUEST })
const { data } = await axios.get(`/api/panel${keyword}`)
dispatch({
type: PANEL_LIST_SUCCESS,
payload: data
})
} catch (error) {
dispatch({
type: PANEL_LIST_FAIL,
payload: error.response && error.response.data.detail
? error.response.data.detail
: error.message,
})
}
}
减速机
export const panelMemberListReducer = (state = { allPanelMembers: [] }, action) => {
switch (action.type) {
case PANEL_LIST_REQUEST:
return { loading: true, allPanelMembers: [] }
case PANEL_LIST_SUCCESS:
return {
loading: false,
allPanelMembers: action.payload.allPanelMembers,
page: action.payload.page,
pages: action.payload.pages
}
case PANEL_LIST_FAIL:
return { loading: false, error: action.payload }
default:
return state
}
}
api终点
http://localhost:8000/api/panel/
在 useSelector 挂钩数据之前访问该值 returns 数据或您的 redux 存储中未定义主要对象。你可以做的是检查这个对象是否存在然后 deconstruct
示例:
const panelMembersList = useSelector(state => state.panelMembersList)
const [panelData, updatePanelData] = useState({
error: '',
loading: false,
allPanelMembers: [],
page: 0,
pages: 0
});
useEffect(() => {
if(panelMembersList) updatePanelData(panelMembersList)
}, [panelMembersList])
或者用默认数据填充 redux 存储中的对象,以防止被识别为未定义
const initialState = {
panelMembersList: {
error: '',
loading: false,
allPanelMembers: [],
page: 0,
pages: 0
}
}
希望我的回答能帮到您解决问题
我想post回答我做错了什么,基本上是在我在端点使用allPanelMembers
访问数据之前,每次我用同样的方法看到我的其他端点时工作正常,但有一个不同之处,我没有在那里使用驼峰命名法,这导致我更改了 django
端的变量,这可能会有所帮助。然后我将 allPanelMembers
更改为 members
没有骆驼案例。这解决了这个问题。曾经有人告诉我,如果我们在前端使用 React,那么在后端使用驼峰命名法,但现在我知道这是不正确的。
正确代码:
#views.py
@api_view(['GET'])
def getAllPanelMember(request):
query = request.query_params.get('keyword')
if query == None:
query = ''
#originaly this variable was named allPanelMembers
members = PanelMember.objects.filter(
name__icontains=query).order_by('-createdAt')
page = request.query_params.get('page')
paginator = Paginator(members, 8)
try:
members = paginator.page(page)
except PageNotAnInteger:
members = paginator.page(1)
except EmptyPage:
members = paginator.page(paginator.num_pages)
if page == None:
page = 1
page = int(page)
#print('Page:', page) If you want to see in termnial
serializer = PanelMemberSerializer(members, many=True)
return Response({'members': serializer.data, 'page': page, 'pages': paginator.num_pages})
前端
import React, { useState, useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { Row, Col, Card, Image, ListGroup, Container } from 'react-bootstrap'
// import PanelMember from '../components/PanelMember'
import Loader from '../components/Loader'
import Message from '../components/Message'
import Paginate from '../components/Paginate'
import { panelMemberList } from '../actions/panelActions'
function PanelListScreen({ history }) {
const dispatch = useDispatch()
const panelList = useSelector(state => state.panelList)
const { error, loading, members, page, pages } = panelList
let keyword = history.location.search
useEffect(() => {
dispatch(panelMemberList(keyword))
}, [dispatch, keyword])
return (
<div>
<h1>Panel</h1>
{loading ? <Loader /> : error ? <Message variant='danger'>{error}</Message> : <div>
<Container>
<Row>
{
members.map(item=>(
<Col key={item._id} sm={12} md={6} lg={4} xl={3}>
<Card.Header>By : {item.name}</Card.Header>
</Col>
))
}</Row></Container></div>}
<Paginate page={page} pages={pages} keyword={keyword} />
</div>
)
}
export default PanelListScreen