我收到这个奇怪的错误,警告:在呈现不同的组件(Cart)时无法更新组件(Connect(Cart)).为了定位Cart内部错误的setState()调用.我不知道真正的问题在哪里,是在cart.js中还是在cartActions.js中?Js使用了Redux Thunk,有时在一个动作创建者中有多个沮丧.先谢谢你.

Cart.js,

import { Component, Fragment } from "react";
import AppNavbar from './AppNavbar';
import { Card, CardText, CardBody, CardTitle, CardSubtitle, Button, Alert, Container } from 'reactstrap';
import PropTypes from 'prop-types';
import { connect }from 'react-redux';
import { getCart, deleteFromCart } from '../actions/cartActions';
import Checkout from "./Checkout";
import { checkout } from '../actions/orderActions';

class Cart extends Component {
    /*state = {
        loaded: false
    }*/

    constructor(props) {
        super(props);
        this.state = {
            loaded: false
        }
    }

    //this.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;
        this.setState({
            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);
        }

        //Why bind this with multiple things below?
        //<Button color="danger" onClick={this.onDeleteFromCart.bind(this, user._id, item.productId)}>Delete</Button>
        return (
            <div>
                <AppNavbar />
                {this.props.isAuthenticated ?
                    <Fragment>
                        {this.props.cart.cart ? null :
                            <Alert color="info" className="text-center">Your cart is empty!</Alert>
                        }
                    </Fragment>
                    : <Alert color="danger" className="text-center">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 tag="h6">USD {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 class="col-md-12">
                            <Card>
                                <CardBody>
                                    <CardTitle  tag="h5">Total Cost = USD {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);

CartActions.js,

//import axios from "axios";
import axios from "../http-common";
import { GET_CART, ADD_TO_CART, DELETE_FROM_CART, CART_LOADING } from "./types";
import { returnErrors } from './errorActions';

export const getCart = (id) => (dispatch) => {
    dispatch(setCartLoading());
    axios.get(`/api/cart/${id}`)
        .then(res => {
            dispatch({
                type: GET_CART,
                payload: res.data
            });
        })
        .catch(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));
    });
}

//My addition for testing below,
/*export const updateCart = (id) => (dispatch) => {
    axios.put(`/api/cart/${id}`)
    .then(res => {
        dispatch({
            type: UPDATE_CART,
            payload: Promise.all([id, 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
    }
}

推荐答案

Issue

该代码正在调度getCart操作,并在render方法中将状态更新排队.两者都有102种副作用.

class Cart extends Component {
  ...

  getCartItems = async (id) => {
    await this.props.getCart(id);    // <-- unintentional side-effect
    this.setState({ loaded: true }); // <-- unintentional side-effect
  }

  render() {
    const user = this.props.user;
    if (this.props.isAuthenticated &&
      !this.props.cart.loading &&
      !this.state.loaded
    ) {
      this.getCartItems(user._id);
    }

    return (
      ...
    );
  }
}

const mapStateToProps = state => ({
  cart: state.cart,
  isAuthenticated: state.auth.isAuthenticated,
  user: state.auth.user
});

const mapDispatchToProps = { getCart, deleteFromCart, checkout }

export default connect(mapStateToProps, mapDispatchToProps)(Cart);

Solution

Reaction呈现函数将被视为102个函数.使用componentDidMountcomponentDidUpdate生命周期方法将这些作为103个副作用发布.

示例:

class Cart extends Component {
  ...

  getCartItems = async () => {
    const { cart, getCart, isAuthenticated, user } = this.props;
    const { loaded } = this.state;

    if (isAuthenticated && !cart.loading && !loaded) {
      await getCart(user.id);
      this.setState({ loaded: true });
    }
  }

  componentDidMount() {
    this.getCartItems();
  }

  componentDidUpdate() {
    this.getCartItems();
  }

  render() {
    // no unintentional side-effects :)

    return (
      ...
    );
  }
}

const mapStateToProps = state => ({
  cart: state.cart,
  isAuthenticated: state.auth.isAuthenticated,
  user: state.auth.user
});

const mapDispatchToProps = { getCart, deleteFromCart, checkout }

export default connect(mapStateToProps, mapDispatchToProps)(Cart);

Reactjs相关问答推荐

在带有和设计的表格中禁用和取消选中复选框

Next.js-图像组件加载问题

react 下拉菜单任务

react 副作用循环

使用筛选器的Primereact DataTable服务器端分页?

StyleX中的多语言支持

使用REACT-RUTER-DOM链接仅更新一个搜索参数

如何解决Reaction中遗留的上下文API错误?

在ReactJS的monaco编辑器中添加美人鱼语法

如何删除 bootstrap 手风琴上的边框

单击按钮不会切换组件(当按钮和组件位于两个单独的文件中时)

无法使axiosmockadapter正常工作

从 React 应用程序调用未经身份验证的 graphql 查询时出现错误:没有当前用户

使用 nextjs App Router 在动态客户端进行服务器端渲染

在 React 中使用复选框管理状态

具有自动完成功能的 Formik material ui 无法按预期工作

react-query、react-hook-form 和表单验证

如何使用 babel 将 SVG 转换为 React 组件?

Lodash 在命名导入中导入整个包

react / firebase 基地.如何在我的项目中保存更新的数据?