Building a React.js App: Managing State in Child Components

Share this video with your friends

Send Tweet

In this video, we’ll walk through how to better manage your state by learning how to manipulate the state of a parent component from a child component.

Kendall
Kendall
~ 9 years ago

Found I had to add ['.value'] to the NotesList render to get just the value back and not the key as well.

So it becomes

{note['.value']}

Marcelo
Marcelo
~ 9 years ago

I am getting an error in the browser console Uncaught Error: Firebase.set failed: First argument contains an invalid key (.key) in property 'jakelingwall.0'. Keys must be non-empty strings and can't contain ".", "#", "$", "/", "[", or "]"

Richard
Richard
~ 9 years ago

I don't know why it is happening but if you change package.json from reactfire ^0.5.0 to ^0.4.0 and then calling npm install... it will fix this problem.

The demo app was built using ^0.4.0 - so it is probably a reasonable fix ... see package.json on https://github.com/tylermcginnis/github-notetaker-egghead

Rich

Junhak
Junhak
~ 9 years ago

https://www.firebase.com/blog/2015-07-15-reactfire-0-5-0.html

Joel Hooks
Joel Hooks
~ 9 years ago

We will update these lessons at some point to reflect the new ReactFire library, but for now, you will want to use v0.4.0

npm install reactfire@0.4.0 --save

Jim Jeffers
Jim Jeffers
~ 9 years ago

To take advantage of the current firebase API you need to add the note like this:

handleAddNote: function(newNote){ this.firebaseRefs['notes'].push({ text: newNote }); }

Also to properly display the contents of a note you'll want to do use the text attribute as the objects in the notes array are objects not strings:

var notes = this.props.notes.map(function(note, index){ return <li className="list-group-item" key={index}>{note.text}</li> })

Tyler McGinnis
Tyler McGinnis(instructor)
~ 9 years ago

Thanks Jim!

Whitney
Whitney
~ 9 years ago

Thanks Jim.

So to clarify for everyone getting the "Uncaught Error: Firebase.set failed: First argument contains an invalid key (.key)" error, you can maintain your latest version of reactfire in package.json but you have to make the simple changes as Jim has specified above. That should fix the error.

Dave Fedele
Dave Fedele
~ 9 years ago

this was super helpful!

Farooq Ali
Farooq Ali
~ 9 years ago

Following works for me in Profile.js:

  handleAddNote: function(newNote, username){
    this.ref.child(username).push(newNote);
  },

And in NoteList.js:

    var notes = this.props.notes.map(function(note, index){
      return <li className="list-group-item" key={index}> {note['.value']} </li>
    });
Minfa
Minfa
~ 9 years ago

I saw that in the video the 'addNote' function was created under the 'Profile' component, and got passed as props to the 'Notes' and 'AddNote' components.

I wonder is there any benefits of doing so? In my point of view, it seems more appropriate to move the 'addNote' function into the 'AddNote' component because it what this component should handle, right?

Thanks.

amitgaur
amitgaur
~ 9 years ago

That would require you to move all the state to the AddNote.js : firebase et all..wouldn't really work since you need to update the NoteList whenever you add a note. Thats why a Mixin is used here.

John Bonaccorsi
John Bonaccorsi
~ 9 years ago

I was wondering the same thing, Minfa. Would love to get a response here. What's the benefit? Seems like it only adds more complexity in having to require it at each level as well.

Joel Hooks
Joel Hooks
~ 9 years ago

There is always more than one way to skin a cat, but the profile seems like a "connected" or "smart" component, versus the notes which are "pure" or "dumb" components and just take whatever they are fed.

egghead eggo
egghead eggo
~ 9 years ago

The lesson video has been updated!

Alan Eng
Alan Eng
~ 9 years ago

Great video. Out of curiosity, would it be tough to submit the note by pressing the enter key instead? Any tips or a guide you can suggest for doing this?

Tyler McGinnis
Tyler McGinnis(instructor)
~ 9 years ago

Not hard at all and it would be a good learning activity. Here's some help if you get stuck. https://gist.github.com/tylermcginnis/3804a4002e45cd6f0ddd

Adam Romines
Adam Romines
~ 9 years ago

Since refs seem to be frowned upon, is there a good reason to use them here? Is there an alternative that would just rely on state? Still slightly shaky on React patterns. Thanks for the tut and thank you for updating!.

Tyler McGinnis
Tyler McGinnis(instructor)
~ 9 years ago

Hi Adam,

That's the first time I've heard about "refs being bad" and I try to be pretty involved in the React community. But to answer your question specifically. You'd need to set a property on the state that's the value of the input field (initially an empty string). Then whenever the value of the input field changes, you'll need to call setState to update the input field. Currently asking around to see if refs are indeed bad, I'll update you if I get any good info.

Tyler McGinnis
Tyler McGinnis(instructor)
~ 9 years ago

Just to make sure I recruited someone smarter than me. Refs are fine in the case in the video. "I'd say don't use refs for component instances. That's what I mean when I say "avoid refs". People tend to use refs to instances and call methods on them. That's usually bad. For DOM refs are useful and can be used just fine IMO" - Dan Abramov

Adam Romines
Adam Romines
~ 9 years ago

That makes sense. Thanks! Have a SO upvote for your troubles!

Abha
Abha
~ 9 years ago

Hi, I am not able to access https://github-note-taker.firebaseio.com/ from my code. If I try to access it directly, it returns me an Authentication Required. Do I need special permissions to access this app or do I need to create my own? ( I am currently logged in using my Google Account in Firebase).. This is my first time with firebase, so I am pretty sure I am missing something, but seems like this is just an example of using a service which returns a piece of data. Could you help me?

Tyler McGinnis
Tyler McGinnis(instructor)
~ 9 years ago

Hi Abha,

You can access all the data from https://github-note-taker.firebaseio.com/ but you won't be able to access the dashboard since it's under my account. If you want to see the actual dashboard you'll need to create your own project. If you just want to use the data that's in the video without being able to see the dashboard, you can use that same github-note-taker link above.

Tyler

Jeremy Zilar
Jeremy Zilar
~ 9 years ago

Question —

  1. In this line, there are three uses of Add Note.
<AddNote username={this.props.username} addNote={this.props.addNote} /> The first is the component, the second is the name of the property that we are passing on to the component, the third is the value of an 'addNote' property that comes from the handleAddNote function in Profile.js and passes (something) over to the Notes component where it ends up here. Is this correct?
  1. I am trying to wrap my head around 'this' at each stage it is used and how the code is using 'this' to pass along data, or how 'this' gets altered when an action is taken. It would help me to visually see how the data is represented at each stage, because it gets a little complex in that Profile.js file.

Is console.log() going to be the best way to view 'this' at each stage?

And thank you — these lessons are really great. Thank you for all the hard work.

Tyler McGinnis
Tyler McGinnis(instructor)
~ 9 years ago
  1. That's correct.
  2. Have you checked out my egghead videos on 'this'. They're actually my favorite videos I've done. There are three of them and this is the first one (https://egghead.io/lessons/javascript-the-this-keyword-introduction-and-implicit-binding). console.log is probably your best bet.

Tyler

Jeremy Zilar
Jeremy Zilar
~ 9 years ago

Wow, great lessons! They were very helpful, thank you!

Ruben
Ruben
~ 9 years ago

Great video, but I'm not completely clear on the ref={this.setRef} part. Will the setRef function be called when the input field is being rendered? Where does the ref parameter of the setRef function come from? Is this automatically set to a reference to the input element?

Cheers, Ruben.

Tyler McGinnis
Tyler McGinnis(instructor)
~ 9 years ago

Hi Ruben,

Sorry for not making this more clear. Your intuition is correct. The way refs work is that they take a callback function which gets passed a specific reference to the input field. So in this case when setRef is invoked, it's passed a reference to our input field which we set to "note" on our instance. Then when we need the value of the input field, we just get it off of "this.note".

Ruben
Ruben
~ 9 years ago

Thanks for clearing that up Tyler. That makes sense.

Thomas Clark
Thomas Clark
~ 8 years ago

Using firebase 3.4.0, I had to add FireBase Config via public/index.html. I'm no longer getting "firebase is not a constructor" error, but my componentDidMount function is now yelling at me with this error: "Uncaught TypeError: Cannot read property 'child' of undefined" after I removed the firebase URL from the DidMount function. Suggestions?

Gerard
Gerard
~ 8 years ago

Running into this error when posting to Firebase:

bundle.js:26415 Uncaught TypeError: Cannot assign to read only property 'addNote' of object '#<Object>' at Object.handleSubmit