Sunday, May 19, 2024
 Popular · Latest · Hot · Upcoming
44
rated 0 times [  48] [ 4]  / answers: 1 / hits: 34057  / 7 Years ago, thu, may 25, 2017, 12:00:00

I currently have a reducer that does a deep copy of state and returns it with the updated value.



function countableItems(state = initialState, action) {
switch (action.type) {
case types.ADD_TO_SUM:
let denomMap = findDenomination(state.denomGroups, action),
nestedCopy = Immutable.fromJS(state);
return nestedCopy.setIn(['denomGroups', denomMap.group, denomMap.key, denomMap.index, 'sum'], parseFloat(action.value)).toJS();
default:
return state;
}
}


In my render function of the display Component I see the correct updated values in this.props.denoms The render() function builds up child <DenomInput> components, and when I set my breakpoints I see the correct data being passed in



render() {
let denomGroups = this.props.denoms.map((denom, i) => {
return (
Object.keys(denom).map((key) => {
let denoms = denom[key].map((item, i) => {
return <DenomInput denom={item} onDenomChange={this.onDenomChange} key={i}></DenomInput>
});
return (<div className=col><h2>{key}</h2>{denoms}</div>)
})
);
});

return (
<div className=countable-item-wrapper>
<div className=row>
{denomGroups}
</div>
</div>
);
}


However when the <DenomInput> components render it renders the same value as what they were initially set



import React, { Component } from 'react';
import PropTypes from 'prop-types';

class DenomInput extends Component {
constructor(props) {
super(props);
this.state = { denom: props.denom }
this.handleKeyUp = this.handleKeyUp.bind(this);
}

handleKeyUp = (e) => {
this.props.onDenomChange(e.target.value, this.state.denom.name);
}

render() {
return (
<div className=input-group denom>
<span className=input-group-addon>{this.state.denom.label}</span>
<input
type=text
className=form-control
onChange={this.handleKeyUp}
value={this.state.denom.sum} />

<span className=input-group-addon>{this.state.denom.count | 0}</span>
</div>
);
}
}

DenomInput.PropTypes = {
denom: PropTypes.object.isRequired,
onDenomChange: PropTypes.function
}

export default DenomInput;


What piece am I missing to update the view with React and Redux?


More From » reactjs

 Answers
11

It looks like you're seeding your initial state with the props from your store. You then render from the component state, but you never update the component state. They only get set once because constructor is only called once the component is rendered. To fix, either remove this component state entirely and just connect it to the redux store, or update the component state onChange. I recommend removing the local state. I have found that keeping the two states in sync is error-prone.



constructor(props) {
super(props);
this.state = { denom: props.denom }
this.handleKeyUp = this.handleKeyUp.bind(this);
}

handleKeyUp = (e) => {
this.props.onDenomChange(e.target.value, this.state.denom.name);
this.setState({ denom: /*new state identitcal to change in redux store*/ })
}


edit2: An example of raising state up. The steps are:

1. Connect one of your parent components and grab the appropriate slice of state with a mapStateToProps function.

2. Pass the props through your connected parent component to DenomInput.

4. In this.denomsChange, dispatch the appropriate action. It is unclear what this is since you did not include your action in the post.



class DenomInput extends Component {
...
render() {
return (
<div className=input-group denom>
<span className=input-group-addon>{this.props.denom.label}</span>
<input
type=text
className=form-control
onChange={this.handleKeyUp}
value={this.props.denom.sum} />

<span className=input-group-addon>{this.props.denom.count | 0}</span>
</div>
);
}
}


export default DenomInput;

[#57658] Tuesday, May 23, 2017, 7 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
sheylap

Total Points: 141
Total Questions: 99
Total Answers: 99

Location: Sint Maarten
Member since Tue, Mar 29, 2022
2 Years ago
;