Commit37 //JS React [Managing Data Flow]
I am studying JavaScript React with @skillcrush, in this module we will cover managing data flow
I am learning with Skillcrush. Please check them out and consider signing up if you're looking to break into tech! Receive $250 off your course by using the link above. Use the coupon code: TWIXMIXY
NOTE: this discount is for Break Into Tech + Get Hired package exclusively. It's the same program I am participating in!
šŖ Greetings travelers! We are continuing our JS React course with Skillcrush. Yesterday I baked some cookies because I had some bananas past their optimal consumption date. So I made banana and peanut butter cookies. They came out alright, but not great!
I definitely have a long way to go in learning how to be better at baking. Itās very likely Iāll be leaving it to the lovely folks on The Great British Bake Off, which we have been enjoying a lot lately in our house.
That hobby will have to wait because for now my focus is on learning how to code JS React! Letās get to it.
Making Your Components Interactive
YES! LETS MAKE THINGS INTERACTIVE!!
Make your UIās components interactive:
Determine the userās intent
Write event handlers to update the data model
Add events listeners
EVENT LISTENERS
Will listen for user events and then trigger your event handlers
Letās Get Interactive
Determine the Userās Intent
Determine, meaning, what do you want the userās intent to be when interacting with this app? For the example we will be working on with the sticky notes it would likely be to make, edit, save and search sticky notes.
Write Event Handlers to Update the Data Model
Then we need to write event handlers to handle each type of action. Thinking specifically about how the data needs to be updated. Are we filtering/searching or are we creating a new note?
Keep in mind with this, that the event handlers must be methods of the component that owns the state. And to update the state, the event handler needs to call on the setState
method of the component which owns the state, for it to actually update it. āI donāt fully understand all this just yet, but Iām beginning to get it!
Add Event Listeners
Finally, we need to listen for the events. So when someone interacts with the UI it will call on an event being handled. These will go into the JSX, where we will reference them as a prop (still not fully understanding props, but hopefully this will help!).
OK⦠letās get to the challenges!
Add a New Note to Your UI
class App extends Component {
state = {
notes: [
{
id: Date.now(),
title: "",
description: "",
doesMatchSearch: true
}
],
searchText: ""
};
addNote = () => {
//create a new note
const newNote = {
id: Date.now(),
title: "",
description: "",
doesMatchSearch: true
};
//add the new note to existing notes array in State
this.setState({ notes: [newNote, ...this.state.notes] });
};
render() {
return (
<div>
<Header addNote={this.addNote} searchText={this.state.searchText} />
<NotesList notes={this.state.notes} />
</div>
);
}
}
We updated our App component to have an addNote
event handler and to start out with an empty sticky note.
<button className="add-new" onClick={props.addNote}>
Also updated the Header component to have an event listener for the new event handler that we just wrote.
Edit Sticky Note Text
onType = (editMeId, updatedKey, updatedValue) => {
//editMeId == id of the note that is edited
//updatedKey == title or description field
//updatedValue == whatever was entered into field, title or description
const updatedNotes = this.state.notes.map((note) => {
if (note.id !== editMeId) {
return note;
} else {
if (updatedKey === "title") {
note.title = updatedValue;
return note;
} else {
note.description = updatedValue;
return note;
}
}
});
this.setState({ notes: updatedNotes });
};
render() {
return (
<div>
<Header addNote={this.addNote} searchText={this.state.searchText} />
<NotesList onType={this.onType} notes={this.state.notes} />
</div>
In the App component we added an event handler called onType for any new information which would be typed into a sticky note. Basically solidifying which note is being updated and what the value will be.
const renderNote = (note) => (
<Note onType={props.onType} note={note} key={note.id} />
);
We ran the prop through our NotesList component.
const Note = (props) => {
// console.log(props);
const updateTitle = (e) => {
const updatedValue = e.target.value;
const editMeId = props.note.id;
props.onType(editMeId, "title", updatedValue);
};
const updateDescription = (e) => {
const updatedValue = e.target.value;
const editMeId = props.note.id;
props.onType(editMeId, "description", updatedValue);
};
return (
<li className="note">
<input
className="note__title"
type="text"
placeholder="Title"
value={props.note.title}
onChange={updateTitle}
/>
<textarea
className="note__description"
placeholder="Description..."
value={props.note.description}
onChange={updateDescription}
/>
<span className="note__delete">X</span>
</li>
);
};
Finally, on the Note component we created event listeners for the onChange on the JSX. This allowed us to finally write in the sticky note and now the data will stick. Well⦠until it refreshes that is, but we will get to local storage at some point to fix that.
Search Notes in Your UI
onSearch = (text) => {
const newSearchText = text.toLowerCase();
const updatedNotes = this.state.notes.map((note) => {
if (!newSearchText) {
note.doesMatchSearch = true;
return note;
} else {
const title = note.title.toLowerCase();
const description = note.description.toLowerCase();
const titleMatch = title.includes(newSearchText);
const descriptionMatch = description.includes(newSearchText);
const hasMatch = titleMatch || descriptionMatch;
note.doesMatchSearch = hasMatch;
return note;
}
});
this.setState({
notes: updatedNotes,
searchText: newSearchText
});
};
render() {
return (
<div>
<Header
onSearch={this.onSearch}
addNote={this.addNote}
searchText={this.state.searchText}
/>
<NotesList onType={this.onType} notes={this.state.notes} />
</div>
);
}
I was interrupted several times during this part, but I will try my best to relay what we did.
In the App component we wrote the event handler for onSearch
. A big thing was changing all the text to lower case, so it could find text no matter the case. We had to write an if statement to basically hide anything that did not match the text, otherwise display the notes that do contain the text. Then we had to add our onSearch
to the header so we could do our work over there.
const Header = (props) => {
const callSearch = (e) => {
props.onSearch(e.target.value);
};
return (
<header>
<h1 className="app-header__title">Super Sticky Notes</h1>
<aside className="app-header__controls">
<button className="add-new" onClick={props.addNote}>
+ New Note
</button>
<input
className="search"
type="text"
placeholder="Type here to search..."
value={props.searchText}
onChange={callSearch}
/>
</aside>
</header>
);
};
Added our onChange
to call the search. Then create our callSearch
event listener.
Finish Your Sticky Note UI
removeNote = (noteId) => {
const updatedNotes = this.state.notes.filter((note) => note.id !== noteId);
this.setState({ notes: updatedNotes });
};
Finally moving on to being able to delete notes. This is basically saying to pull back the notes that havenāt been deleted.
render() {
return (
<div>
<Header
onSearch={this.onSearch}
addNote={this.addNote}
searchText={this.state.searchText}
/>
<NotesList
removeNote={this.removeNote}
onType={this.onType}
notes={this.state.notes}
/>
</div>
);
}
This integrates the ability to remove notes into the main App component
const renderNote = (note) => (
<Note
removeNote={props.removeNote}
onType={props.onType}
note={note}
key={note.id}
/>
);
We then had to tie it into our NotesList component.
const clickDelete = () => {
props.removeNote(props.note.id);
};
Finally pull it into the individual Note component so we know which one is being deleted.
Now, we need to make sure these notes stay in our local storage so we donāt lose our list.
componentDidUpdate() {
const stringifiedNotes = JSON.stringify(this.state.notes);
localStorage.setItem("savedNotes", stringifiedNotes);
}
componentWillMount() {
const stringifiedNotes = localStorage.getItem("savedNotes");
if (stringifiedNotes) {
const savedNotes = JSON.parse(stringifiedNotes);
this.setState({ notes: savedNotes });
}
}
I looked it up on how it was done for the Name Tag app, but Iām still unsure which properties/values are made up ones and which are native to JS React. Iām sure I could have tinkered with it to find out, but instead I just tried my best to pay attn to what we were doing in this challenge.
So there it is! We have a fully functional Sticky Notes app.
Quiz: Make Components Interactive
Only one wrong!
Question #8: Event handlers must be _______ of the component that owns the state.
Your Answer: Expressions
Correct Answer: Methods
Darn! I even had this written in my notes above, but I didnāt double check.
Iām looking forward to coming up with my own project after doing this!
What was your first project? Leave me a comment below!