Even after passing updated value from parent to child, child is not rendered












0














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>);
}
}









share|improve this question





























    0














    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>);
    }
    }









    share|improve this question



























      0












      0








      0







      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>);
      }
      }









      share|improve this question















      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






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Dec 27 at 14:47









      Ian Kemp

      16.4k126797




      16.4k126797










      asked Dec 27 at 14:17









      Anakii Eugene

      6510




      6510
























          2 Answers
          2






          active

          oldest

          votes


















          1














          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.






          share|improve this answer





















          • 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



















          0














          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>
          );
          });
          }





          share|improve this answer





















            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
            });


            }
            });














            draft saved

            draft discarded


















            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









            1














            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.






            share|improve this answer





















            • 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
















            1














            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.






            share|improve this answer





















            • 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














            1












            1








            1






            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.






            share|improve this answer












            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.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            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 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
















            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













            0














            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>
            );
            });
            }





            share|improve this answer


























              0














              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>
              );
              });
              }





              share|improve this answer
























                0












                0








                0






                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>
                );
                });
                }





                share|improve this answer












                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>
                );
                });
                }






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Dec 28 at 8:48









                Anakii Eugene

                6510




                6510






























                    draft saved

                    draft discarded




















































                    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.




                    draft saved


                    draft discarded














                    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





















































                    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







                    Popular posts from this blog

                    Monofisismo

                    Angular Downloading a file using contenturl with Basic Authentication

                    Olmecas