【问题标题】:React-Redux: Changes in state by different reducerReact-Redux:不同减速器的状态变化
【发布时间】:2019-02-01 18:47:23
【问题描述】:

我正在构建这个自动售货机的小项目,但我遇到了问题,因为我的状态的两个不同部分从一个只应该改变一个部分的减速器发生了变化。以下是代码 sn-ps :

//Action creators

export const buyProduct = product => {
	return {
		type: 'BUY_PRODUCT',
		payload: product
	};
};

export const showProducts = () => {
	return {
		type: 'SHOW_PRODUCTS',
	};
};

export const addCredit = amount => {
	return {
		type: 'ADD_MONEY',
		payload: amount
	};
};

export const refillVendingMachine = () => {
	return {
		type: 'REFILL_VENDING_MACHINE'
	};
};

//Reducers

import { combineReducers } from 'redux';

const data = [
	{code: '110', price: 10, name: 'KitKat', quantity: 5, image: 'https://i.ibb.co/41dKJ8r/kitkat.jpg'},
	{code: '111', price: 11, name: 'Nuggets', quantity: 5, image: 'http://lorempixel.com/135/100/food'},
	{code: '112', price: 12, name: 'Mars', quantity: 5, image: 'http://lorempixel.com/135/100/food'},
	{code: '113', price: 13, name: 'Twix', quantity: 5, image: 'http://lorempixel.com/135/100/food'},
	{code: '114', price: 14, name: '7days', quantity: 5, image: 'http://lorempixel.com/135/100/food'}, 
	{code: '115', price: 15, name: 'Water', quantity: 5, image: 'http://lorempixel.com/135/100/food'},
	{code: '210', price: 14, name: '7days', quantity: 5, image: 'http://lorempixel.com/135/100/food'},
	{code: '211', price: 14, name: '7days', quantity: 5, image: 'http://lorempixel.com/135/100/food'},
	{code: '212', price: 14, name: '7days', quantity: 5, image: 'http://lorempixel.com/135/100/food'}
	];

const productsReducer = (products = data, action) => {
	if(action.type === 'BUY_PRODUCT') {
		return products.map(product => {
			if(product.code === action.payload.code) {
				if(product.quantity === 1) {
					product.quantity--;
					product.image = "https://i.ibb.co/w0sSgpd/sold-out.png";
					return product;
				};		
				product.quantity--		
				return product;
			};
			return product;	
		});
	}
	
	return products;
};


const moneyReducer = (state = 0, action) => {
	if(action.type === 'BUY_PRODUCT') {
		return state - parseInt(action.payload.price);
	} else if(action.type === "ADD_MONEY") {
		return state + parseInt(action.payload);
	}
	return state;
};

const boughtProductsReducer = (state = [], action) => {
	if(action.type === 'BUY_PRODUCT') {
		if(state.length === 3){
			state.shift();
		}
		return [...state, action.payload]
	};

	return state;
};


export default combineReducers({
	products: productsReducer,
	money: moneyReducer,
	boughtProducts: boughtProductsReducer
});

正如您在自动售货机中遇到的那样,当产品的数量变为 0 时,它应该仅在产品状态下显示已售罄,但它也会更改在购买产品状态下的图像。

知道为什么吗?以及如何解决?

更新:

这里是我展示所有产品的地方,也是我需要更改图片的地方

import React from 'react';
import './Rows.css';
import './Product.css';
import { connect } from 'react-redux';


class Rows extends React.Component {
	renderRows = () => {

			return this.props.products.map(product => {

				return (
					<div className="this">
					<div className="product" key={product.code}>
						<div className="body">
							<div className="title">
								{product.name}
							</div>
							<div className="image">
								<img alt="blablabla" src={product.image} />
							</div>
						</div>
						<div className="extra">
							<span className="text">Q: {product.quantity}</span>
						</div>
						</div>
						<div className="content">
							<span className="text">#{product.code}</span>
							<span className="text">{product.price} $</span>
						</div>
					
					</div>
				);
			});
		
	};

	render() {
		return (
			<React.Fragment>
				{this.renderRows()}
			</React.Fragment>
		);
	};
};

const mapStateToProps = state => {
	console.log(state);
	return {products: state.products};
	};
export default connect(mapStateToProps)(Rows);

这里是我存储购买产品的地方,图像应该保持不变

import React from 'react';
import { connect } from 'react-redux';
import './Bin.css';

class Bin extends React.Component {
	renderBin = () => {
		console.log(this.props.boughtProducts);
		return this.props.boughtProducts.map(product => {
			return <div className="product" key={product.code*Math.random()}>
					<div className="body">
						<div className="title">
							{product.name}
						</div>
						<div className="image">
							<img alt="blablabla" src={product.image} />
						</div>
					</div>
				</div>
		});
	};

 render() {
 	return (
 		<div className="bin">
 			<i className="fas fa-angle-right fa-9x color"></i>
 			<div className="product-bin">
 				{this.renderBin()}
 			</div>
 		</div>
 		);
 };
};

const mapStateToProps = state => {
	return {boughtProducts: state.boughtProducts};
};

export default connect(mapStateToProps)(Bin);

【问题讨论】:

  • 您也可以发布您的反应代码吗?这可能会有所帮助。我假设您的一项操作是由生命周期方法触发的,该方法由您的减速器之一的状态更改触发。
  • 嘿@Mark 这些动作都是由反应应用程序中的按钮触发的。没有生命周期方法。我添加了显示状态的组件。触发器在不同的触发器上,你也需要它们吗?

标签: redux react-redux


【解决方案1】:
const productsReducer = (products = data, action) => {
if(action.type === 'BUY_PRODUCT') {
    return products.map(product => {
        if(product.code === action.payload.code) {
            if(product.quantity === 1) {
                product.quantity--;
                product.image = "https://i.ibb.co/w0sSgpd/sold-out.png";
                return product;
            };      
            product.quantity--      
            return product;
        };
        return product; 
    });
}

return products;
};

这部分代码改变了图片的url,产品页面也使用了相同的图片。因此,变化也反映在那里。您可以通过像这样有条件地渲染来修复它

<img alt="blablabla" src={product.quantity === 0 ? `sold-out-image-path`: product.image} />

如果您对所有产品使用相同的售罄图片,这将正常工作。如果售罄图像取决于产品,那么您可以为该内部数据添加一个属性[]。

{code: '110', price: 10, name: 'KitKat', quantity: 5, image: 'https://i.ibb.co/41dKJ8r/kitkat.jpg', soldOutImage: 'product-specific-sold-out-image'},

然后像这样写UI代码

<img alt="blablabla" src={product.quantity === 0 ? product.soldOutImage: product.image} />

希望我对你有帮助:-)

【讨论】:

  • 感谢 Aman,这行得通,但我仍然不明白为什么数据也改变了购买的产品状态。有什么想法吗?
  • 这是因为对于 'BUY_PRODUCT' 操作,会调用多个减速器,包括购买的ProductsReducer,因此由于单个操作而修改了多个状态。如果我有帮助,请点赞。
猜你喜欢
  • 1970-01-01
  • 2019-02-01
  • 2016-06-04
  • 1970-01-01
  • 2016-04-23
  • 1970-01-01
  • 2018-09-12
  • 2020-03-27
  • 1970-01-01
相关资源
最近更新 更多