The part of my app in question is utilizing 4 components, 1 parent and 3 children. As expected, the parent component handles all state and passes values to child components via props.
The parent component contains methods for updating state changes, also passed down via props. The child components do not have state other than component methods, they use only props for visual data.
The problem I’m having is that when I call the method to update parent state, the parent state is updated successfully (verified via the console), however the child component, which reflects this state via its props, doesn’t render the state change visually.
The code is below which I’ll do my best to explain:
Parent component update state method:
handleUpvoteState(blurtIndex) {
let blurts = [...this.state.followingBlurts],
updatedBlurt = {...blurts[blurtIndex]};
updatedBlurt.vote++;
blurts[blurtIndex] = updatedBlurt;
this.setState({
followingBlurts: blurts
});
console.log(this.state.followingBlurts[blurtIndex].vote); // State change reflected.
}
Parent component passing state to child props:
<LazyBlurtsPanel
appendDate={this.state.appendDate}
random={this.state.randomize}
blurts={this.state.followingBlurts}
handleLazyState={this.handleLazyState}
handleUpvoteState={this.handleUpvoteState}
lazyElement='lzyfollowing'
apiMethod={this.state.apiMethod}
currentUser={false}
/>
The lazy panel component (above) then sends data to footer child via props:
<BlurtFooter
voteCount={this.props.blurts[i].vote}
currentUser={this.props.currentUser}
blurtId={this.props.blurts[i]._id}
blurtIndex={i}
handleUpvoteState={this.props.handleUpvoteState}
/>
When I call
this.props.handleUpvoteState(index)
in my child footer component, the parent state is successfully updated. However, the footer component doesn't re-render to reflect the parent's updated state.
Here's the footer component code that isn't getting re-rendered:
render() {
return (
<div className="blurt-panel-footer">
<UpvoteCount voteCount={this.props.voteCount}/>
Any help much appreciated.
EDIT: There was some confusion as to how blurtfooter is called, so I'm including the code for how the panel is built inside a loop within LazyBlurtPanel component. Here's the code for that:
for(let i=numRendered; i<renderCount; i++) {
if (this.props.blurts[i]) {
renderBlurts.push(
<div className='blurt-panel' id={(((i + 1) % 6) === 0) ? this.props.lazyElement : 'false'} key={i}>
<BlurtHeader blurt={this.props.blurts[i]} />
<div className='blurt-panel-body'>
<Sanitizer dirty={ this.props.blurts[i].text } />
{
(this.props.blurts[i].blurtImg !== 'false')? <img src={'/images/blurt/' + this.props.blurts[i].blurtImg} /> : ''
}
</div>
<BlurtFooter
voteCount={this.props.blurts[i].vote}
currentUser={this.props.currentUser}
blurtId={this.props.blurts[i]._id}
blurtIndex={i}
handleUpvoteState={this.props.handleUpvoteState}
key={this.props.blurts[i]._id} //Tried with and without key here..
/>
</div>
);
}
}
let blurts = JSON.parse(JSON.stringify(this.state.followingBlurts));
try this. – sk01console.log
in therender()
method of yourLazyBlurtsPanel
to see if it is being rerendered after the state change. If I'm right you are renderingBlurtFooter
in a loop, then you shoud see a warning about missing key property. Not sure if it can cause this problem, but try addingkey={this.props.blurts[i]._id}
– Dimitri L.