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.
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']}
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 "]"
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
https://www.firebase.com/blog/2015-07-15-reactfire-0-5-0.html
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
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>
})
Thanks Jim!
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.
this was super helpful!
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>
});
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.
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.
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.
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.
The lesson video has been updated!
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?
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
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!.
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.
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
That makes sense. Thanks! Have a SO upvote for your troubles!
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?
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
Question —
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
Wow, great lessons! They were very helpful, thank you!
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.
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".
Thanks for clearing that up Tyler. That makes sense.
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?
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