为什么在调度更改redux存储的操作后,我的react组件没有重新呈现?

时间:2019-06-22 18:27:36

标签: javascript reactjs redux

我只是在玩Redux,因此对任何错误或不良做法表示歉意。

我基本上有计算机部件的列表,用户可以选择/取消选择这些部件。每个部分都是一个JS对象,其中包含ID,名称,价格和所选字段:

const initialState = {
    products: [
        {product_id: 0, product_name: "Hard Drive 320 GB 5400 RPM", price: 1450, selected: false},
        {product_id: 1, product_name: "Solid State Drive 128 GB R/W - 420 MB/s", price: 1880, selected: false},
        {product_id: 2, product_name: "Gigabyte MB A270S AM4 DDR4 3200HZ OC HDMI/VGA/DVI", price: 3560, selected: false},
        {product_id: 3, product_name: "Asus MB A420M LGA 1151 3200HZ OC HDMI/VGA", price: 3660, selected: false},
        {product_id: 4, product_name: "nVidia GTX 1050 Ti 4GB GDDR5 VRAM", price: 13450, selected: false},
        {product_id: 5, product_name: "Intel i5 7200 kabylake CPU 3.6 GHz 4 cores 4 threads", price: 9800, selected: false},
        {product_id: 6, product_name: "AMD Ryzed 5 2600G CPU 3.2 GHz 4 cores 4 threads", price: 9380, selected: false},
        {product_id: 7, product_name: "8 GB Hyper-X DDR4 RAM memory 3200 MHz CL15", price: 3450, selected: false},
        {product_id: 8, product_name: "450W Sharkoon PSU 80 plus black semi modular", price: 2250, selected: false},
        {product_id: 9, product_name: "ATX Case w/ Acrilyc Glass panel & LED Strips", price: 1720, selected: false},
    ],
    sum: 0
}

(这只是一种惯例,因此我不会从rest api或其他工具加载数据)

然后,我使用connect函数通过App组件订阅redux存储,并传入mapStateToProps和mapDispatchToProps函数:

function mapStateToProps(state){
    return {
        products: state.products,
        sum: state.sum
    }
}

function mapDispatchToProps(dispatch){
    return {
        toggle: (product_id) => dispatch(ACTIONS.toggle(product_id))
    }
}


export default connect(mapStateToProps, mapDispatchToProps)(App)

然后在我的应用程序组件内部,创建一个const数组,我将所有产品映射到该数组,并生成一个div的JSX返回,其中包含内容,然后在每个div上添加一个事件linstener(onClick),该事件触发this.props.toggle调度:

const products = this.props.products.map(product => {
    return (
        <div className="product" key={product.product_id} onClick={ () => {this.props.toggle(product.product_id) }}>
            <h2>{product.product_name}</h2>
            {product.selected ? ('') : (<h3>{product.price}</h3>)}
        </div>
    )
})

当分派动作时,这就是在reducer中发生的事情:

switch(action.type){
    case ACTION_TYPES.PRODUCT_TOGGLE:
        const newState = state
        newState.products[action.payload].selected = !newState.products[action.payload].selected
        if(newState.products[action.payload].selected === true){
            newState.sum = newState.sum + newState.products[action.payload].price
        } else {
            newState.sum = newState.sum - newState.products[action.payload].price
        }
        console.log(newState.sum)
        return newState
    default:
        return state
}

如果我在化简版中进行控制台登录,我确实会看到更改的发生,但是容器组件的道具不会更新。

2 个答案:

答案 0 :(得分:2)

您要突变state对象,newStatestate是相同的对象引用,这就是UI不更新的原因。

您必须从化简器返回一个新对象。

在像这样对对象进行变异之前创建一个新对象

const newState = { ...state }

答案 1 :(得分:1)

当您运行newState = state时,您只是在创建一个变量,该变量引用与旧状态相同的对象,因此,当您为该对象分配新值时,您就是在对旧对象进行突变。

Redux和React-Redux使用严格的相等性检查来确定您的状态是否已更新。由于对象引用相同,因此认为状态没有改变。

const oldState = { a: 1 };
const newState = oldState;
newState.a = 2;
console.log(oldState);
console.log(newState);
console.log(oldState === newState);

请参阅有关不变性的这篇文章:https://redux.js.org/faq/immutable-data#why-is-immutability-required-by-redux