简体   繁体   中英

unable to fetch update redux state in state less component reactjs

In my reactJs app I'm using redux-thunk, when I'm updating redux state my stateless component is not getting updated state value.
my Addons.js

import React from 'react';
import {connect} from 'react-redux';
import {addOnSelected, addonsCount, updateVehData} from '../../actions'
import { Card,Row,Col,Avatar } from 'antd';
import { Collapse} from 'antd';
const Panel = Collapse.Panel;
import HelperImg from '../../../public/images/Helper.png'

const Addons = (props)=>{
    console.log(props.VehcileData,"asd")
    let addonsCards = [];

    const addonsCard = (addon)=>{
        addonsCards.push(
            <Col lg={{span:7,offset:1}} key={addon.text} style={{paddingBottom:'2rem'}}>
            <Card
            type="inner"
            // title="Small Vehicle"
            id='addonCard'
            hoverable
            onClick={(e)=>{(e.target.id !== 'minus' && e.target.id !== 'adQty' && e.target.id !== 'plus') && props.updateVehData(addon) }}
            className={`${addon.selected ? 'addSelected' :''} ad_card`}
        >
            <Row type="flex" justify="space-around" align="middle" gutter={16}>
                <Col lg={{span:16}} xs={{span:24}} style={{padding:'0px'}} >
                    <div className='ad_img' align='middle'>
                        <Avatar src={HelperImg} />
                    </div>
                    <div align='middle'>
                    <h3 className='ad_title'>{addon.text}</h3>
                    </div>
                </Col>
                <Col lg={{span:16,offset:5}} xs={{span:16,offset:5}}>
                    <div className="input-group">
                        <input type="button" value=" - " id='minus' className="button-minus" onClick={()=>props.addonsCount(addon)}/>
                        <input type="number"  className="quantity-field" id='adQty'/>
                        <input type="button" value="+" className="button-plus" id="plus"/>
                    </div>
                </Col>
                <Col lg={{span:24}} xs={{span:24}} className='price'>
                    <div className='ad_price'>
                        <h3>Price RS 2000</h3>
                    </div>
                </Col>
            </Row>

        </Card>
        </Col>)
    }
    const loopVData =()=>{
        for (const key of Object.keys(props.VehcileData)) {
            if(props.VehcileData[key].vid === props.VSelected){
                props.VehcileData[key].mand.map((addon,i)=>{
                    addonsCard(addon)
                })
                props.VehcileData[key].pre.map((addon,i)=>{
                    addonsCard(addon)
                })

                props.VehcileData[key].optn.map((addon,i)=>{
                    addonsCard(addon)
                })
            }
        }
    }
    return(
        <div>
            <Collapse defaultActiveKey={['1','2']} >
            <Panel header="SELECT ADDONS" key="1">
                <Row >

                    {loopVData()}
                    {addonsCards}
                </Row>
            </Panel>
            </Collapse>
        </div>
    )
}


const mapStateToProps = (state) =>{
    console.log(state.StepThreeReducer.vehcileData)
    return{
        VehcileData:state.StepThreeReducer.vehcileData,
        VSelected:state.StepThreeReducer.isAmbSel
    }
}
export default connect(mapStateToProps,{addOnSelected,addonsCount,updateVehData})(Addons);

my ACTION.js

export function updateVehData(val){
    return function(dispatch,getState){
        if(val.type === 'opt'){
            let VehData = getState().StepThreeReducer.vehcileData;
            let vehID =getState().StepThreeReducer.isAmbSel;            
            for (const key of Object.keys(VehData)) {
                // console.log(VehData[key])
                if(VehData[key].vid === vehID){
                    VehData[key].optn.forEach(addon=>{
                        if(addon._id==val._id){
                            addon.selected = !addon.selected;
                            if(addon.selected === true){
                                addon.qty=1;
                            }else if(addon.selected === true){
                                addon.qty=0;
                            }
                        }
                    });

                }
            }
            dispatch({type:VEHICLEDATA,payload:VehData})
        }
    }
}

my Reducer.js

import {ISAMBSEL,ADDONSEL,TOTALPRICE,VEHICLEDATA} from '../actions/types';
const INITIAL_STATE = {
    isAmbSel:null,
    addonSel:[],
    vehcileData:0,

};
export default  (state=INITIAL_STATE,action) => {
    // console.log(action,'reducer')
    switch(action.type) {
        case ISAMBSEL:
            return {...state,isAmbSel:action.payload};
        case ADDONSEL:
            return {...state,addonSel:[...action.payload]}
        case TOTALPRICE:
            return {...state,totalPrice:action.payload}
        case VEHICLEDATA:{
            return {...state,vehcileData:action.payload}}
        default:
            return state;
    }
}

in my mapStateToProps function if I console the state.StepThreeReducer.vehcileData I'm getting updated value but when I console value inside Addons component it is not showing the props.VehcileData value even after updating redux state it's not rendering
but the same time it's parent component is showing the updated redux state value if I send the updated state value through parent component to my Addons component then also it's not showing updated value of redux state.
I think I don't have any problem in Actions or Reducer because in mapStateToProps it is showing real time redux state value.

let VehData = getState().StepThreeReducer.vehcileData;
let vehID = getState().StepThreeReducer.isAmbSel;
for (const key of Object.keys(VehData)) {
  // console.log(VehData[key])
  if (VehData[key].vid === vehID) {
    VehData[key].optn.forEach(addon => {
      if (addon._id == val._id) {
        addon.selected = !addon.selected;
        if (addon.selected === true) {
          addon.qty = 1; // <-- mutating
        } else if (addon.selected === true) {
          addon.qty = 0; // <-- mutating
        }
      }
    });
  }
}

When mapStateToProps will get call it will check diff b/w your prevState and nextState so that it can decide that components needs to be updated or not .

And your case you are mutating the state here only and after updating in reducer the prevState will be same as what you are updating in reducer.

You should try deep cloning it or change the procedure.

also you should you an middleware (redux-immutable-state-invariant) which will detect mutation in redux and throws warnings.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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