1

I am trying to simply render each tag in my database for the user. Only the last tag is rendering (tag3) for the user. The console reads something like this:

Console:

...
Room.js:376 Tags just before .map: undefined
Room.js:376 Tags just before .map: undefined
Room.js:376 Tags just before .map: undefined
Room.js:376 Tags just before .map: undefined
Room.js:376 Tags just before .map: tag1
Room.js:376 Tags just before .map:  tag2
Room.js:376 Tags just before .map:  tag3

Database Structure:

>questions
    >ID1234567890
          >body
          >title
          >tags
              >0
                 >tag: tag1
              >1
                 >tag: tag2
              >2
                 >tag: tag3
              >tagCount: 3
          >status

I've tried a couple methods of doing this, like making a <Tag> component, passing that the values and rendering them through that, but can't get the tags to render properly. I feel like I am close since the console is logging the correct values, but the render is not working. How do I get each tag to render?

Room.js:

<b>Tags:</b>
{console.log("Tags just before .map: " + this.state.questionTags)}
{
  this.state.questionTags &&
  (

    this.state.questionTags.map((tag) => {
      return (
        <div>
        {tag}
        </div>
    )
    })
  )
} 

Setting questionTags:

//Grab tag data
fire
  .database()
  .ref('/questions/' + this.state.questionId + '/tags/')
  .once('value')
  .then(
    function(snapshot) {
      var tagCount = snapshot.val().tagCount;
      this.setState({
        tagCount: tagCount
      });
      var i = 0;
      for (i = 0; i < tagCount; i++) {
        fire
          .database()
          .ref('/questions/' + this.state.questionId + '/tags/' + i)
          .once('value')
          .then(
            function(snapshot) {
              this.setState({
                questionTags: [snapshot.val().tag]
              });
            }.bind(this)
          );
      }
    }.bind(this)
  );
3
  • 1
    Where/How are you setting this.state.questionTags? Commented Jan 21, 2019 at 18:55
  • @KhauriMcClain updated the post with that bit! Commented Jan 21, 2019 at 19:10
  • 1
    Ah, seems you're rewriting questionTags each time instead of appending the new tag to the existing array. Something else to note is that you might consider just getting all the question tags in one go rather than in a loop like that. Commented Jan 21, 2019 at 19:23

2 Answers 2

1

You need to set unique key to div element inside map. Since I am not sure how your data looks like or it contains unique id per object so I am using index from map as a key to div element.

Whenever you render jsx elements inside loop, you need to set unique key to top jsx element inside loop so in your case the top jsx element is div otherwise what is happening in your case is that since you are not setting unique key you will get only last rendered jsx element.

Change

this.state.questionTags.map((tag) => {
        return (
             <div>
                 {tag}
             </div>
        )
   })

To

this.state.questionTags.map((tag, index) => {
        return (
             <div key={"key-"+index}
                  {tag}
             </div>
        )
   })

Edit:

In The for loop you are doing setState for every iteration so you are getting only the last tag. You should push all tags into an array and after the for loop set those tags array to the state. Try with below updated code

      //Grab tag data
       fire.database().ref('/questions/' + this.state.questionId + '/tags/').once('value').then(function(snapshot) { 
         var tagCount = snapshot.val().tagCount;
         this.setState({
            tagCount: tagCount,
         })
        var i = 0;
        const tags = [];
        for(i = 0; i < tagCount; i++){
    fire.database().ref('/questions/'+this.state.questionId+'/tags/'+i).once('value').then(function(snapshot) { 
            tags.push(snapshot.val().tag);
          }.bind(this));
        }
        this.setState({
                questionTags: tags
            })
      }.bind(this));
Sign up to request clarification or add additional context in comments.

8 Comments

Tried these changes, nothing changed :/
@DangerDoug I have updated my answer please check edit section
Amazing, worked, thanks so much man. Was getting pretty frustrated lol.
Actually quick follow up, I just noticed when I reload the page using your code block, the tag data is gone, but with mine the tag3 is still there on reload. How do you think I fix this?
Looks like the tags appear on reload only if I open and close a react-modal on the page? Weird; I'll explore it or ask a separate question.
|
0

with arrow function:

fire.database().ref('/questions/' + this.state.questionId + '/tags/').once('value').then(snapshot => { 
     var tagCount = snapshot.val().tagCount;
     this.setState({
        tagCount
     })
    var i = 0;
    let tags = [];
    for(i = 0; i < tagCount; i++){
fire.database().ref('/questions/'+this.state.questionId+'/tags/'+i).once('value').then(snapshot => { 
        tags.push({ tag: snapshot.val().tag });
      });
    }
    this.setState({
            questionTags: tags
        })
  });

2 Comments

Thanks, but adding arrow functions causes an error. Hemadri's answer worked, except the tags are not there on reload. Any idea on that?
but also change tags.push and change const to let in tags, does that also give you an error?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.