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 thatrender
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 callsetState
on calling map function inside mytoggleSelection
function 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 thatrender
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 callsetState
on calling map function inside mytoggleSelection
function 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 thatrender
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 callsetState
on calling map function inside mytoggleSelection
function 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 thatrender
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 callsetState
on calling map function inside mytoggleSelection
function 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 thatrender
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 callsetState
on calling map function inside mytoggleSelection
function 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