如何解决TypeError:无法解构“panelMembersList”的属性“error”,因为它未定义
我正在尝试使用 Django REST API
和 redux
从 axios
服务器加载数据,我在其他屏幕(如产品、博客帖子)中使用的类似方法,它们工作正常,现在我需要从 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,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 钩子返回数据之前正在访问该值,或者在您的 redux 存储中未定义主对象。你可以做的是检查这个对象是否存在然后解构
示例:
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: '',pages: 0
}
}
希望我的回答能帮助您解决问题
,我想发布我的答案我做错了什么,基本上是在我在端点使用 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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。