Even after passing updated value from parent to child, child is not rendered
In the parent component, I receive data from the server and then map this data into a jsx format. Inside this mapping I have a child component and try to pass a value from state of parent to child as a property, however when I update state of this value, the render function for child is not executed.
Expected behavior: As a user I see a list of items. If I click on an item it should become as checked.
export class ReactSample extends React.Component {
constructor(props){
super(props);
this.state = {
items: ,
mappedItems: ,
selectedIds: ,
isSelected: false,
clickedTripId: null
};
this.toggleSelection = this.toggleSelection.bind(this);
}
componentWillMount(){
console.log("Component mounting")
}
toggleSelection (id, e) {
if(!_.includes(this.state.selectedIds, id)) {
this.setState((state) => ({selectedIds:
state.selectedIds.concat(id)}));
this.setState(() => ({clickedTripId: id}));
this.mapItems(this.state.items);
}
}
componentDidMount() {
const self = this;
MyService.getItems()
.then(res => {
self.setState(() => ({ items: res.allItems }));
self.setState(() => ({ mappedItems:
this.mapItems(res.allItems) }));
}
)
}
mapItems (items) {
return items.map(trip => {
return (
<li key={trip.id} onClick={(e) => (this.toggleSelection(trip.id,
e))}>
<span>{trip.title}</span>
<Tick ticked={this.state.clickedTripId}/>
<span className="close-item"></span>
</li>
);
});
}
getItems() {
}
render() {
return (
<div>
<a className="title">This is a react component!</a>
<Spinner showSpinner={this.state.items.length <= 0}/>
<div className="items-container">
<ul id="itemsList">
{this.state.mappedItems}
</ul>
</div>
</div>
);
}
}
export class Tick extends React.Component {
constructor(props) {
super(props);
}
render() {
console.log('RENDER');
return (<span className={this.props.ticked ? 'tick display' :
'tick hide' }></span>);
}
}
javascript reactjs
add a comment |
In the parent component, I receive data from the server and then map this data into a jsx format. Inside this mapping I have a child component and try to pass a value from state of parent to child as a property, however when I update state of this value, the render function for child is not executed.
Expected behavior: As a user I see a list of items. If I click on an item it should become as checked.
export class ReactSample extends React.Component {
constructor(props){
super(props);
this.state = {
items: ,
mappedItems: ,
selectedIds: ,
isSelected: false,
clickedTripId: null
};
this.toggleSelection = this.toggleSelection.bind(this);
}
componentWillMount(){
console.log("Component mounting")
}
toggleSelection (id, e) {
if(!_.includes(this.state.selectedIds, id)) {
this.setState((state) => ({selectedIds:
state.selectedIds.concat(id)}));
this.setState(() => ({clickedTripId: id}));
this.mapItems(this.state.items);
}
}
componentDidMount() {
const self = this;
MyService.getItems()
.then(res => {
self.setState(() => ({ items: res.allItems }));
self.setState(() => ({ mappedItems:
this.mapItems(res.allItems) }));
}
)
}
mapItems (items) {
return items.map(trip => {
return (
<li key={trip.id} onClick={(e) => (this.toggleSelection(trip.id,
e))}>
<span>{trip.title}</span>
<Tick ticked={this.state.clickedTripId}/>
<span className="close-item"></span>
</li>
);
});
}
getItems() {
}
render() {
return (
<div>
<a className="title">This is a react component!</a>
<Spinner showSpinner={this.state.items.length <= 0}/>
<div className="items-container">
<ul id="itemsList">
{this.state.mappedItems}
</ul>
</div>
</div>
);
}
}
export class Tick extends React.Component {
constructor(props) {
super(props);
}
render() {
console.log('RENDER');
return (<span className={this.props.ticked ? 'tick display' :
'tick hide' }></span>);
}
}
javascript reactjs
add a comment |
In the parent component, I receive data from the server and then map this data into a jsx format. Inside this mapping I have a child component and try to pass a value from state of parent to child as a property, however when I update state of this value, the render function for child is not executed.
Expected behavior: As a user I see a list of items. If I click on an item it should become as checked.
export class ReactSample extends React.Component {
constructor(props){
super(props);
this.state = {
items: ,
mappedItems: ,
selectedIds: ,
isSelected: false,
clickedTripId: null
};
this.toggleSelection = this.toggleSelection.bind(this);
}
componentWillMount(){
console.log("Component mounting")
}
toggleSelection (id, e) {
if(!_.includes(this.state.selectedIds, id)) {
this.setState((state) => ({selectedIds:
state.selectedIds.concat(id)}));
this.setState(() => ({clickedTripId: id}));
this.mapItems(this.state.items);
}
}
componentDidMount() {
const self = this;
MyService.getItems()
.then(res => {
self.setState(() => ({ items: res.allItems }));
self.setState(() => ({ mappedItems:
this.mapItems(res.allItems) }));
}
)
}
mapItems (items) {
return items.map(trip => {
return (
<li key={trip.id} onClick={(e) => (this.toggleSelection(trip.id,
e))}>
<span>{trip.title}</span>
<Tick ticked={this.state.clickedTripId}/>
<span className="close-item"></span>
</li>
);
});
}
getItems() {
}
render() {
return (
<div>
<a className="title">This is a react component!</a>
<Spinner showSpinner={this.state.items.length <= 0}/>
<div className="items-container">
<ul id="itemsList">
{this.state.mappedItems}
</ul>
</div>
</div>
);
}
}
export class Tick extends React.Component {
constructor(props) {
super(props);
}
render() {
console.log('RENDER');
return (<span className={this.props.ticked ? 'tick display' :
'tick hide' }></span>);
}
}
javascript reactjs
In the parent component, I receive data from the server and then map this data into a jsx format. Inside this mapping I have a child component and try to pass a value from state of parent to child as a property, however when I update state of this value, the render function for child is not executed.
Expected behavior: As a user I see a list of items. If I click on an item it should become as checked.
export class ReactSample extends React.Component {
constructor(props){
super(props);
this.state = {
items: ,
mappedItems: ,
selectedIds: ,
isSelected: false,
clickedTripId: null
};
this.toggleSelection = this.toggleSelection.bind(this);
}
componentWillMount(){
console.log("Component mounting")
}
toggleSelection (id, e) {
if(!_.includes(this.state.selectedIds, id)) {
this.setState((state) => ({selectedIds:
state.selectedIds.concat(id)}));
this.setState(() => ({clickedTripId: id}));
this.mapItems(this.state.items);
}
}
componentDidMount() {
const self = this;
MyService.getItems()
.then(res => {
self.setState(() => ({ items: res.allItems }));
self.setState(() => ({ mappedItems:
this.mapItems(res.allItems) }));
}
)
}
mapItems (items) {
return items.map(trip => {
return (
<li key={trip.id} onClick={(e) => (this.toggleSelection(trip.id,
e))}>
<span>{trip.title}</span>
<Tick ticked={this.state.clickedTripId}/>
<span className="close-item"></span>
</li>
);
});
}
getItems() {
}
render() {
return (
<div>
<a className="title">This is a react component!</a>
<Spinner showSpinner={this.state.items.length <= 0}/>
<div className="items-container">
<ul id="itemsList">
{this.state.mappedItems}
</ul>
</div>
</div>
);
}
}
export class Tick extends React.Component {
constructor(props) {
super(props);
}
render() {
console.log('RENDER');
return (<span className={this.props.ticked ? 'tick display' :
'tick hide' }></span>);
}
}
javascript reactjs
javascript reactjs
edited Dec 27 at 14:47
Ian Kemp
16.4k126797
16.4k126797
asked Dec 27 at 14:17
Anakii Eugene
6510
6510
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
I see a couple issues.
In toggleSelection you aren't doing anything with the result of mapItems. This kind of bug would be much easier to avoid if you just remove mappedItems from state and instead just call mapItems within your render method.
The other issue is you are passing this.state.clickedTripId as the ticked property. I assume you meant to pass something more like this.state.clickedTripId === trip.id.
Thank you Ryan for your replay. Initially, I had done mapping in the render function but then I read from official documentation thatrenderfunction should be kept as a cleaner as it is possible. That is why I moved "mappings" into another place. But you are right that I do nothing with mapped items. My map class function returns a result and I had to callsetStateon calling map function inside mytoggleSelectionfunction in order to updatemappedItems!
– Anakii Eugene
Dec 28 at 8:27
add a comment |
As Ryan already said, the problem was that mappedItems where not updated when toggleSelection was clicked. As it is obvious from the code mapItems returns data in jsx format. To update it I had to call this.setState({mappedItems: this.mapItems(this.state.items)}) which means that I call mapItems and then I assign the result to the state. In this case my list will be updated and Tick component will receive this.state.clickedItemId as a tick property. There is one more issue that needs to be done to make this code working:
this mapped list needs to be updated after this.state.clickedItemId is updated. The method setState is asynchronous which means that this.setState({mappedItems: this.mapItems(this.state.items)}) has to be called only after this.state.clickedItemId is updated. To achieve this, the setState method can receive a callback function as a second parameter. The code snippet is the following:
toggleSelection (id, e) {
if(!_.includes(this.state.selectedIds, id)) {
this.setState((state) => ({
clickedItemId: id,
selectedIds: state.selectedIds.concat(id)
}), () => this.setState({mappedItems: this.mapItems(this.state.items)}));
}
}
In this case, at the time the mapItems function is executed all data from the state that is needed here will be already updated:
mapItems (items) {
return items.map(item => {
return (
<li key={item.id} onClick={(e) => (this.toggleSelection(item.id, e))}>
<span>{item.title}</span>
<span>{this.state.clickedItemId}</span>
<Tick ticked={this.state.clickedItemId === item.id}/>
<span className="close-item"></span>
</li>
);
});
}
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53946499%2feven-after-passing-updated-value-from-parent-to-child-child-is-not-rendered%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
I see a couple issues.
In toggleSelection you aren't doing anything with the result of mapItems. This kind of bug would be much easier to avoid if you just remove mappedItems from state and instead just call mapItems within your render method.
The other issue is you are passing this.state.clickedTripId as the ticked property. I assume you meant to pass something more like this.state.clickedTripId === trip.id.
Thank you Ryan for your replay. Initially, I had done mapping in the render function but then I read from official documentation thatrenderfunction should be kept as a cleaner as it is possible. That is why I moved "mappings" into another place. But you are right that I do nothing with mapped items. My map class function returns a result and I had to callsetStateon calling map function inside mytoggleSelectionfunction in order to updatemappedItems!
– Anakii Eugene
Dec 28 at 8:27
add a comment |
I see a couple issues.
In toggleSelection you aren't doing anything with the result of mapItems. This kind of bug would be much easier to avoid if you just remove mappedItems from state and instead just call mapItems within your render method.
The other issue is you are passing this.state.clickedTripId as the ticked property. I assume you meant to pass something more like this.state.clickedTripId === trip.id.
Thank you Ryan for your replay. Initially, I had done mapping in the render function but then I read from official documentation thatrenderfunction should be kept as a cleaner as it is possible. That is why I moved "mappings" into another place. But you are right that I do nothing with mapped items. My map class function returns a result and I had to callsetStateon calling map function inside mytoggleSelectionfunction in order to updatemappedItems!
– Anakii Eugene
Dec 28 at 8:27
add a comment |
I see a couple issues.
In toggleSelection you aren't doing anything with the result of mapItems. This kind of bug would be much easier to avoid if you just remove mappedItems from state and instead just call mapItems within your render method.
The other issue is you are passing this.state.clickedTripId as the ticked property. I assume you meant to pass something more like this.state.clickedTripId === trip.id.
I see a couple issues.
In toggleSelection you aren't doing anything with the result of mapItems. This kind of bug would be much easier to avoid if you just remove mappedItems from state and instead just call mapItems within your render method.
The other issue is you are passing this.state.clickedTripId as the ticked property. I assume you meant to pass something more like this.state.clickedTripId === trip.id.
answered Dec 27 at 14:44
Ryan C
1,302211
1,302211
Thank you Ryan for your replay. Initially, I had done mapping in the render function but then I read from official documentation thatrenderfunction should be kept as a cleaner as it is possible. That is why I moved "mappings" into another place. But you are right that I do nothing with mapped items. My map class function returns a result and I had to callsetStateon calling map function inside mytoggleSelectionfunction in order to updatemappedItems!
– Anakii Eugene
Dec 28 at 8:27
add a comment |
Thank you Ryan for your replay. Initially, I had done mapping in the render function but then I read from official documentation thatrenderfunction should be kept as a cleaner as it is possible. That is why I moved "mappings" into another place. But you are right that I do nothing with mapped items. My map class function returns a result and I had to callsetStateon calling map function inside mytoggleSelectionfunction in order to updatemappedItems!
– Anakii Eugene
Dec 28 at 8:27
Thank you Ryan for your replay. Initially, I had done mapping in the render function but then I read from official documentation that
render function should be kept as a cleaner as it is possible. That is why I moved "mappings" into another place. But you are right that I do nothing with mapped items. My map class function returns a result and I had to call setState on calling map function inside my toggleSelection function in order to update mappedItems!– Anakii Eugene
Dec 28 at 8:27
Thank you Ryan for your replay. Initially, I had done mapping in the render function but then I read from official documentation that
render function should be kept as a cleaner as it is possible. That is why I moved "mappings" into another place. But you are right that I do nothing with mapped items. My map class function returns a result and I had to call setState on calling map function inside my toggleSelection function in order to update mappedItems!– Anakii Eugene
Dec 28 at 8:27
add a comment |
As Ryan already said, the problem was that mappedItems where not updated when toggleSelection was clicked. As it is obvious from the code mapItems returns data in jsx format. To update it I had to call this.setState({mappedItems: this.mapItems(this.state.items)}) which means that I call mapItems and then I assign the result to the state. In this case my list will be updated and Tick component will receive this.state.clickedItemId as a tick property. There is one more issue that needs to be done to make this code working:
this mapped list needs to be updated after this.state.clickedItemId is updated. The method setState is asynchronous which means that this.setState({mappedItems: this.mapItems(this.state.items)}) has to be called only after this.state.clickedItemId is updated. To achieve this, the setState method can receive a callback function as a second parameter. The code snippet is the following:
toggleSelection (id, e) {
if(!_.includes(this.state.selectedIds, id)) {
this.setState((state) => ({
clickedItemId: id,
selectedIds: state.selectedIds.concat(id)
}), () => this.setState({mappedItems: this.mapItems(this.state.items)}));
}
}
In this case, at the time the mapItems function is executed all data from the state that is needed here will be already updated:
mapItems (items) {
return items.map(item => {
return (
<li key={item.id} onClick={(e) => (this.toggleSelection(item.id, e))}>
<span>{item.title}</span>
<span>{this.state.clickedItemId}</span>
<Tick ticked={this.state.clickedItemId === item.id}/>
<span className="close-item"></span>
</li>
);
});
}
add a comment |
As Ryan already said, the problem was that mappedItems where not updated when toggleSelection was clicked. As it is obvious from the code mapItems returns data in jsx format. To update it I had to call this.setState({mappedItems: this.mapItems(this.state.items)}) which means that I call mapItems and then I assign the result to the state. In this case my list will be updated and Tick component will receive this.state.clickedItemId as a tick property. There is one more issue that needs to be done to make this code working:
this mapped list needs to be updated after this.state.clickedItemId is updated. The method setState is asynchronous which means that this.setState({mappedItems: this.mapItems(this.state.items)}) has to be called only after this.state.clickedItemId is updated. To achieve this, the setState method can receive a callback function as a second parameter. The code snippet is the following:
toggleSelection (id, e) {
if(!_.includes(this.state.selectedIds, id)) {
this.setState((state) => ({
clickedItemId: id,
selectedIds: state.selectedIds.concat(id)
}), () => this.setState({mappedItems: this.mapItems(this.state.items)}));
}
}
In this case, at the time the mapItems function is executed all data from the state that is needed here will be already updated:
mapItems (items) {
return items.map(item => {
return (
<li key={item.id} onClick={(e) => (this.toggleSelection(item.id, e))}>
<span>{item.title}</span>
<span>{this.state.clickedItemId}</span>
<Tick ticked={this.state.clickedItemId === item.id}/>
<span className="close-item"></span>
</li>
);
});
}
add a comment |
As Ryan already said, the problem was that mappedItems where not updated when toggleSelection was clicked. As it is obvious from the code mapItems returns data in jsx format. To update it I had to call this.setState({mappedItems: this.mapItems(this.state.items)}) which means that I call mapItems and then I assign the result to the state. In this case my list will be updated and Tick component will receive this.state.clickedItemId as a tick property. There is one more issue that needs to be done to make this code working:
this mapped list needs to be updated after this.state.clickedItemId is updated. The method setState is asynchronous which means that this.setState({mappedItems: this.mapItems(this.state.items)}) has to be called only after this.state.clickedItemId is updated. To achieve this, the setState method can receive a callback function as a second parameter. The code snippet is the following:
toggleSelection (id, e) {
if(!_.includes(this.state.selectedIds, id)) {
this.setState((state) => ({
clickedItemId: id,
selectedIds: state.selectedIds.concat(id)
}), () => this.setState({mappedItems: this.mapItems(this.state.items)}));
}
}
In this case, at the time the mapItems function is executed all data from the state that is needed here will be already updated:
mapItems (items) {
return items.map(item => {
return (
<li key={item.id} onClick={(e) => (this.toggleSelection(item.id, e))}>
<span>{item.title}</span>
<span>{this.state.clickedItemId}</span>
<Tick ticked={this.state.clickedItemId === item.id}/>
<span className="close-item"></span>
</li>
);
});
}
As Ryan already said, the problem was that mappedItems where not updated when toggleSelection was clicked. As it is obvious from the code mapItems returns data in jsx format. To update it I had to call this.setState({mappedItems: this.mapItems(this.state.items)}) which means that I call mapItems and then I assign the result to the state. In this case my list will be updated and Tick component will receive this.state.clickedItemId as a tick property. There is one more issue that needs to be done to make this code working:
this mapped list needs to be updated after this.state.clickedItemId is updated. The method setState is asynchronous which means that this.setState({mappedItems: this.mapItems(this.state.items)}) has to be called only after this.state.clickedItemId is updated. To achieve this, the setState method can receive a callback function as a second parameter. The code snippet is the following:
toggleSelection (id, e) {
if(!_.includes(this.state.selectedIds, id)) {
this.setState((state) => ({
clickedItemId: id,
selectedIds: state.selectedIds.concat(id)
}), () => this.setState({mappedItems: this.mapItems(this.state.items)}));
}
}
In this case, at the time the mapItems function is executed all data from the state that is needed here will be already updated:
mapItems (items) {
return items.map(item => {
return (
<li key={item.id} onClick={(e) => (this.toggleSelection(item.id, e))}>
<span>{item.title}</span>
<span>{this.state.clickedItemId}</span>
<Tick ticked={this.state.clickedItemId === item.id}/>
<span className="close-item"></span>
</li>
);
});
}
answered Dec 28 at 8:48
Anakii Eugene
6510
6510
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53946499%2feven-after-passing-updated-value-from-parent-to-child-child-is-not-rendered%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown