The reaction is not updated when the state of Redux changes below the first level.

I have my state in Redux and I use the react-redux connector to bind it in my React application. During initial startup, where the state is set, the connection works fine. However, when I update part of the state in my reducer, it is not read as modified with React, so the component does not display again. When I do another action that forces the render, the state was actually changed.

This seems to be due to the fact that the state was not recognized as changed, and in the response-redux method for wrapWithConnect, the storeChanged and procsChanged objects are both evaluated as false after the first run. The key may be that the reduction reaction is compared at a shallow level in these tests.

The question " what do I need to do to get React to display changes in my state when the state changes in Redux "

The corresponding part of the state is below

let thisOrder = Immutable.fromJS( { "projectNumber": '', "orderHeader": { "order_id": "", "firstname": "", "lastname": "", "address1": "", ), "orderProducts": [], "lastOperation": ''} ); 

The section that is being updated is orderProducts, an array of products that basically looks like

  orderProducts:[{productSKU:'Y54345',productDesc:'What it is',price:"4.60",qty:2}, {productSKU:'Y54345',productDesc:'What what is',price:"9.00",qty:1}] 

When updating qty or price in the gearbox below (caused by an action), the resulting newState has changes

  case OrderConstants.ORDER_PRODUCT_UPDATE:{ let productList = updateProductList( action.updateProduct, state.get( 'orderProducts' )) let newState = state.update( 'orderProducts', productList).set('lastOperation', action.type); return newState;} 

And finally, the React control component, which then sends the downstream props

  render: function () { return ( <div> <ProductList updateOrder={this.updateOrder()} products={this.props.products}/> {this.submitContinueButton()} {this.submitButton()} {this.cancelButton()} </div> </div> ) } } ); // connect to Redux store var mapStateToProps = function ( state ) { return { ocoStore: state.toJS(), products: state.get('orderProducts')}; }; export default connect( mapStateToProps )( OrderProducts ); 

All of the above is clipped to the relevant sections. Please note that the code works to display product information on the lower components at boot time. This is when updating the price or quantity that the update does not occur.

+5
source share
1 answer

I replicated your solution using JSBIN and I managed to get it working, so I thought I would share it if it helps you.

Below is the code as shown in JSBIN. It is based on code snippets in your question. Please note that you did not specify the code for your updateProductList method and the code for the ProductList component, so I had to create my own.

 const initialState = Immutable.fromJS({ "projectNumber": '', "orderHeader": { "order_id": "", "firstname": "", "lastname": "", "address1": "", }, "orderProducts": [ { productSKU: 'Y54345', productDesc: 'What it is', price: "4.60", qty:2 }, { productSKU: 'Y54346', productDesc: 'What what is', price:"9.00", qty:1 } ], "lastOperation": '' }); const updateProductList = (updateProduct, productList) => { return productList.map(product => { if (product.get('productSKU') === updateProduct.productSKU) { return Immutable.fromJS(updateProduct); } return product; }); }; const order = (state = initialState, action) => { switch (action.type) { case 'ORDER_PRODUCT_UPDATE': let updatedProductList = updateProductList(action.updateProduct,state.get('orderProducts')); const newState = state.set( 'orderProducts', updatedProductList).set('lastOperation', action.type); return newState; default: return state; } }; const { combineReducers } = Redux; const orderApp = combineReducers({ order }); const { Component } = React; const { Provider, connect } = ReactRedux; const ProductList = ({ products }) => { return (<ul> {products.map(product => { return ( <li key={product.get('productSKU')}> {product.get('productSKU')} - {product.get('productDesc')} - {product.get('qty')} </li> ); } )} </ul>); }; const OrderProducts = ({ ocoStore, products, dispatch }) => ( <div> <ProductList products={products} /> <a href='#' onClick={e => { e.preventDefault(); dispatch({ type: 'ORDER_PRODUCT_UPDATE', updateProduct: { productSKU: 'Y54345', productDesc: 'What it is', price: "4.60", qty: 8 } }); }}>Update Product Y54345</a> </div> ) const mapStateToProps = ( state ) => { return { ocoStore: state.order.toJS(), products: state.order.get('orderProducts') }; }; const OrderApp = connect(mapStateToProps)(OrderProducts); const { createStore } = Redux; ReactDOM.render( <Provider store={createStore(orderApp)}> <OrderApp /> </Provider>, document.getElementById('root') ); 

JSBIN: http://jsbin.com/qabezuzare

The part of my code that is different is as follows:

  const newState = state.set( 'orderProducts', updatedProductList).set('lastOperation', action.type); 

This is because my updateProductList method returns a new Immutable.List file.

I hope that working on a working solution will help you fix your problem.

+1
source

Source: https://habr.com/ru/post/1238202/


All Articles