简体   繁体   English

如何在 redux 商店中正确更新道具?

[英]How to properly update props in redux store?

I have a React App with a shopping cart component.我有一个带有购物车组件的 React 应用程序。 I use Redux to update the shopping cart when clicking on a "Add to cart" button in an item.单击项目中的“添加到购物车”按钮时,我使用 Redux 更新购物车。 The problem is, even I update the props in the item component, the prop is not updating concurrently.问题是,即使我更新了项目组件中的道具,道具也不会同时更新。 When I'm checking the props in the component in the Chrom developer tools components tab, I can see the props are updating only when I navigate to another component.当我在 Chrom 开发人员工具组件选项卡中检查组件中的道具时,只有当我导航到另一个组件时,我才能看到道具正在更新。 However, the cart component never receives the updated prop to populate the cart items.但是,购物车组件永远不会收到更新的道具来填充购物车项目。 These are the necessary components.这些是必要的组件。

Items component物品组件

import React, { Component } from 'react';
import ProductData from './DataSet/ProductData';
import { compose } from 'recompose';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { updateCartList } from '../../store/actions';

class LatestProducts extends Component {

    addItemToCart = (id) => {
        const { cartList, updateCartList } = this.props;
        var items = cartList;
        ProductData.forEach(each => {
            if (each.id === id) {
                items.push(each)
            }
        });
        updateCartList(items);
    }

    render() {

        return (
            <div>
                <div className="itemGridMain">
                    {
                        ProductData.map(product => {
                            return (
                                <div className="itemCard" key={product.id}>
                                    <button onClick={() => this.addItemToCart(product.id)}>Add to cart</button>
                                </div>
                            )
                        })
                    }
                </div>
            </div>
        );
    }
}

function mapStateToProps(state) {
    return {
        cartList: state.cartList,
    };
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators({
        updateCartList: updateCartList,
    }, dispatch);
}

export default compose(connect(mapStateToProps, mapDispatchToProps))(LatestProducts);

Cart component购物车组件

import React, { Component } from 'react';
import { compose } from 'recompose';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { updateCartList } from '../../store/actions';

class FrontHeader extends Component {

    render() {

        const { cartList } = this.props;

        return (
            <div className="cartList">
                {
                    cartList && cartList.length > 0 && cartList.map(item => {
                        return (
                            <div className="listItem" key={item.id}>
                            </div>
                        )
                    })
                }
            </div>
        );
    }
}

function mapStateToProps(state) {
    return {
        cartList: state.cartList,
    };
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators({
        updateCartList: updateCartList,
    }, dispatch);
}

export default compose(connect(mapStateToProps, mapDispatchToProps))(FrontHeader);

Cart List Reducer购物车列表缩减器

const cartListReducer = (state = [], action) => {
    switch (action.type) {
        case 'UPDATE_CARTLIST':
            return action.payload;
        default:
            return state;
    }
}

export default cartListReducer;

Cart List Index购物车列表索引

import cartListReducer from './cartlist';
import { combineReducers } from 'redux';

const allReducers = combineReducers({
    cartList: cartListReducer,
})

export default allReducers;

Redux Actions Redux 操作

export const updateCartList = (newCartList) => {
    return {
        type: 'UPDATE_CARTLIST',
        payload: newCartList,
    }
}

How can I solve this?我该如何解决这个问题?

Issue问题

this.props.cartList is your state and by pushing into that array and saving it back into state you are simply mutating state. this.props.cartList是您的状态,通过推入该数组并将其保存回状态,您只是在改变状态。

addItemToCart = (id) => {
    const { cartList, updateCartList } = this.props;
    var items = cartList; // <-- state reference
    ProductData.forEach(each => {
        if (each.id === id) {
            items.push(each) // <-- push into state reference
        }
    });
    updateCartList(items); // <-- saved state reference
}

Solution解决方案

You should provide a new array object reference for react to pick up the difference since reconciliation uses shallow object equality.您应该为 react 提供一个新的数组对象引用以获取差异,因为协调使用浅层对象相等性。

Your addItemToCart should probably just take the item you want added to the cart and move the cart update logic to the reducer.您的addItemToCart可能应该只是将您想要添加到购物车的项目并将购物车更新逻辑移动到减速器。

LatestProducts最新产品

class LatestProducts extends Component {

  addItemToCart = (item) => {
    const { updateCartList } = this.props;
    updateCartList(item); // <-- pass item to action creator
  }

  render() {
    return (
      <div>
        <div className="itemGridMain">
          {ProductData.map(product => {
            return (
              <div className="itemCard" key={product.id}>
                <button
                  onClick={() => this.addItemToCart(product)} // <-- pass product/item
                >
                  Add to cart
                </button>
              </div>)
            })
          }
        </div>
      </div>
    );
  }
}

cartListReducer购物车列表减速器

const cartListReducer = (state = [], action) => {
  switch (action.type) {
    case 'UPDATE_CARTLIST':
      return [...state, action.payload]; // <-- copy state and appen new item

    default:
      return state;
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM