【问题标题】:Redux state changes but not reflected in componentRedux 状态更改但未反映在组件中
【发布时间】:2021-11-16 06:10:56
【问题描述】:

我正在尝试使用 redux 实现购物车。这是我的购物车减速器:

export const cartReducer = (
state = { cartItems: JSON.parse(localStorage.getItem("cartItems") || "[]")},
action) => {
switch (action.type) {
 case ADD_TO_CART:
  return { ...state,cartItems: action.payload };
}}

这是我想要显示更新的状态值的组件,使用连接中的道具访问它并在每次状态更新后更新 cartItems.length

class Cartsidebar extends Component {
    constructor(props) {
        super(props);
        this.state = {
            grandTotal: '',toggle:true
        }
    }
    handleHide(){
        this.setState({ toggle: !this.state.toggle})
    }
    render() {
        
     const {cartItems}=this.props;
     console.log(cartItems);
        return (
            <div>
               {cartItems.length}

            </div>
        )
    }
}

export default connect(
    (state) => ({
        cartItems: state.cart.cartItems,
    }),
    { incrementToCart, decreaseToCart, removeFromCart }
)(Cartsidebar);

状态更新正常,每次 redux 状态更新时,redux-dev-tools 中也会显示状态差异,但它没有反映在购物车组件中。我在这里做错了什么?提前致谢。

编辑: 这是在添加到购物车按钮 onclick 事件时执行的函数:

handleAddToCart=(p)=>{
const cartItems = store.getState().cart.cartItems;
  let alreadyExists = false;
  cartItems.forEach((x) => {
    if (x.discountPer === p.discountPer) {
      alreadyExists = true;
    }
  });
  if (!alreadyExists) {
    cartItems.push({ ...p });
  }


store.dispatch(addToCart(cartItems));
     
}

addToCart 动作创建器看起来像这样:

export const addToCart = (cartItem) => {
  return({
    type: ADD_TO_CART,
    payload: cartItem,
  });
};

【问题讨论】:

  • 调用添加到购物车时您的代码是什么样的?
  • @apachuilo 我已经进行了编辑以包括操作和 addToCart 处理程序。
  • 我可能弄错了,但您添加到购物车的方式是可变的。我认为除非它是一个新数组,否则 redux 不会认识到这一点。为了测试起见,您可以查看将调度更改为 store.dispatch(addToCart([...cartItems])); 是否有帮助。
  • 链接到讨论一些不可变更新模式的文档redux.js.org/usage/structuring-reducers/…
  • 尝试了您建议的修复方法。但仍然无法正常工作

标签: reactjs redux react-redux react-props redux-reducers


【解决方案1】:

问题

  1. 您正在改变状态对象。您正在访问状态中的购物车数组的引用并直接推入它。
  2. 您没有正确利用 Redux 和 reducer 的强大功能。

代码

handleAddToCart = (p) => {
  const cartItems = store.getState().cart.cartItems; // cartItems is reference to state
  let alreadyExists = false;
  cartItems.forEach((x) => {
    if (x.discountPer === p.discountPer) {
      alreadyExists = true;
    }
  });
  if (!alreadyExists) {
    cartItems.push({ ...p }); // mutation!!
  }

  store.dispatch(addToCart(cartItems));
}

解决方案

在操作中传递您要添加到购物车的商品,并将所有更新购物车的逻辑移动到您的减速器中。

用户界面

handleAddToCart = (p) => {
  this.props.addToCart(p);
}

...

export default connect(
  (state) => ({
    cartItems: state.cart.cartItems,
  }),
  { addToCart, incrementToCart, decreaseToCart, removeFromCart }
)(Cartsidebar);

减速器

case ADD_TO_CART:
  const { payload } = action;
  const found = state.cartItems.find(item => item.discountPer === payload.discountPer);

  if (found) {
    return state;
  }

  return {
    ...state,
    cartItems: state.cartItems.concat(payload),
  };

【讨论】:

  • 非常感谢@Drew Reese。这完全解决了我的问题
【解决方案2】:

你在handleAddToCart 中所做的事情是一个很大的禁忌,并且违背了 Redux 试图强制执行的模式。我对您的逻辑进行了一些更改以使其更容易,并更新了减速器。理论上,如果您进行这些更改,它应该可以工作。

handleAddToCart:

handleAddToCart = (p) => {
  const cartItems = store.getState().cart.cartItems;

  for (const item of cartItems) {
    if (item.discountPer === p.discountPer) {
      return;
    }
  }

  store.dispatch(addToCart({ ...p }));
};

减速器:

export const cartReducer = (
  state = { cartItems: JSON.parse(localStorage.getItem("cartItems") || "[]") },
  action
) => {
  switch (action.type) {
    case ADD_TO_CART:
      return { ...state, cartItems: [...state.cartItems, action.payload] };
  }
};

【讨论】:

  • 感谢 Dan 的回答。这确实有帮助。但我只能接受一个答案
猜你喜欢
  • 2019-08-31
  • 2020-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多