javascript - 未处理的拒绝(TypeError):无法在我的 cartActions.js 中读取未定义的属性(读取“数据”)
问题描述
我正在尝试在我的反应应用程序中使用 axios 进行身份验证时加载用户的购物车,但它返回一个错误,提示“无法读取未定义的属性(读取'数据')”。该错误突出显示了我的 cartAction.js:15 这是一个 .catch 方法,它返回错误响应数据和状态,但是当我 console.log 来自我的 axios.get( /api/cart/${id}
) 的响应时,它在我的控制台中成功记录了响应,但它没有t 在我的反应应用程序中呈现。我认为问题出在我的 Cart.js 组件代码中,但我似乎无法纠正它。我的 cartAction.js getCart 常量中的 console.log(err) 打印“错误:Checkout(...): 没有从渲染返回。这通常意味着缺少返回语句。或者,不渲染任何内容,返回 null。 ”在我的控制台中
这是我的 cartAction.js 代码
> export const getCart = (id) => dispatch => {
> dispatch(setCartLoading());
> axios.get(`/api/cart/${id}`)
> .then(res => dispatch({
> type: GET_CART,
> payload: res.data
> })
> )
> .catch(err => {
> console.log(err)
> dispatch(returnErrors(err.response.data, err.response.status))}); }
>
> export const addToCart = (id, productId, quantity) => dispatch => {
> axios.post(`/api/cart/${id}`, {productId, quantity})
> .then(res => dispatch({
> type: ADD_TO_CART,
> payload: res.data
> }))
> .catch(err => dispatch(returnErrors(err.response.data, err.response.status))); }
>
> export const deleteFromCart = (userId, itemId) => dispatch => {
> axios.delete(`/api/cart/${userId}/${itemId}`)
> .then(res => dispatch({
> type: DELETE_FROM_CART,
> payload: res.data
> }))
> .catch(err => dispatch(returnErrors(err.response.data, err.response.status))); }
>
> export const setCartLoading = () => {
> return{
> type: CART_LOADING
> } }
这是我的组件/Cart.js 代码
class Cart extends Component{
state = {
loaded: false
}
static propTypes = {
getCart: PropTypes.func.isRequired,
isAuthenticated: PropTypes.bool,
addToCart: PropTypes.func.isRequired,
deleteFromCart: PropTypes.func.isRequired,
user: PropTypes.object.isRequired,
cart: PropTypes.object.isRequired,
checkout: PropTypes.func.isRequired
}
getCartItems = async (id) => {
await this.props.getCart(id);
this.state.loaded = true;
}
onDeleteFromCart = (id, itemId) => {
this.props.deleteFromCart(id, itemId);
}
render(){
const user = this.props.user;
if(this.props.isAuthenticated && !this.props.cart.loading && !this.state.loaded){
this.getCartItems(user._id);
}
return(
<div>
<AppNavbar/>
{this.props.isAuthenticated ?
<Fragment>
{ this.props.cart.cart ? null :
<Alert className="text-center" color="info">Your cart is empty!</Alert>
}
</Fragment>
: <Alert className="text-center" color="danger">Login to View</Alert>
}
{this.props.isAuthenticated && !this.props.cart.loading && this.state.loaded && this.props.cart.cart ?
<Container>
<div className="row">
{this.props.cart.cart.items.map((item)=>(
<div className="col-md-4">
<Card>
<CardBody>
<CardTitle tag="h5">{item.name}</CardTitle>
<CardSubtitle>NGN {item.price}</CardSubtitle>
<CardText>Quantity - {item.quantity}</CardText>
<Button color="danger" onClick={this.onDeleteFromCart.bind(this, user._id, item.productId)}>Delete</Button>
</CardBody>
</Card>
<br/>
</div>
))}
<div className="col-md-12">
<Card>
<CardBody>
<CardTitle tag="h5">Total Cost = NGN. {this.props.cart.cart.bill}</CardTitle>
<Checkout
user={user._id}
amount={this.props.cart.cart.bill}
checkout={this.props.checkout}
/>
</CardBody>
</Card>
</div>
</div>
</Container>
: null
}
</div>
);
}
}
const mapStateToProps = (state) => ({
cart: state.cart,
isAuthenticated: state.auth.isAuthenticated,
user: state.auth.user
})
export default connect(mapStateToProps, {getCart, deleteFromCart, checkout})(Cart);
这是我的 cartReducer.js 代码
const initialState = {
cart: null,
loading: false
}
export default function cartReducer (state=initialState, action){
switch(action.type){
case GET_CART:
return {
...state,
cart: action.payload,
loading: false
}
case ADD_TO_CART:
return {
...state,
cart: action.payload
}
case DELETE_FROM_CART:
return {
...state,
cart: action.payload
}
case CART_LOADING:
return {
...state,
loading: true
}
default:
return state;
}
}
解决方案
我想我现在看到了这个问题。render
您正在从您的方法中发出副作用。render
被认为是一个同步的纯函数。如果您需要获取数据,它应该在组件生命周期方法之一中,即componentDidMount
和/或componentDidUpdate
.
将“getCartItems”条件逻辑移动到实用程序函数中并从componentDidMount
生命周期方法中调用。
fetchCartItems = () => {
const { cart, isAuthenticated, user } = this.props;
const { loaded } = this.state;
if (isAuthenticated && !cart.loading && !loaded) {
this.getCartItems(user._id);
}
}
componentDidMount() {
this.fetchCartItems();
}
...
render() {
const { user } = this.props;
return (
<div>
...
</div>
);
}
如果在组件安装后您可能需要稍后再次获取购物车项目,例如,身份验证状态发生更改,请使用该componentDidUpdate
方法。
componentDidUpdate() {
this.fetchCartItems();
}
推荐阅读
- swift - UIStackView 中差异元素的大小(宽度/高度)约束覆盖彼此的约束
- azure - 使用 azure java sdk 对 Azure 进行身份验证
- google-colaboratory - 如何在 google colab 中生成代码单元?
- python - 可以在python的discord api中使用相对路径吗?
- c# - 使用带有 Selenium 的 specflow 只运行一次 BeforeTestRun 和 AfterTestRun
- angular - Angular Google Charts:如何为柱形图中的列设置不同的颜色
- javascript - 赋予角色的 Discord.js 命令
- url - #:~:text= 在 url 中做什么?
- php - 如何用 laravel 制作水晶报表?
- javascript - 编写一个程序,将变量 num 转换为字符串。变数 = 35.36 ; 删除点以在浏览器中显示“3536”。如何执行此操作