https://medium.com/@nataliebarba/build-a-basic-app-in-react-part-i-9c6c27dbfc41
Build a Basic App in React, Part I
A couple of weeks ago, I wrote about beginning Flatiron School’s Software Engineering bootcamp.
This week we made the jump from learning Vanilla JavaScript to React. Though fundamental concepts are shared, perhaps the biggest difference between the two is the way that code is structured and data is shared. In this post, we’ll review components and props as we begin to build a basic to-do app in React.
Quick Overview
So what are components? React documentation states:
“Components let you split UI into independent, reusable pieces, and think about each piece in isolation.”
In other words, we want to split our app’s code into components that help us separate responsibilities. Components resemble Vanilla JavaScript functions and they return JSX.
What about props? Essentially, props are units of information we want to pass down from a parent component to a child component. We define the props keys and values within the parent component.
We’ll see examples of components and props below.
Set Up a Basic App
Assuming we already have React installed on our machines, all we have to do is run the following in terminal to get a basic React app started for us:
npx create-react-app to-do-list cd to-do-list npm start
What we did here was create an app called “to-do-list”, navigated to it, and opened it in our browser.
Let’s go ahead and open “to-do-list” in our code editor. We’ll see that there are a series of files already set up for us — we’re ready to start making this basic app ours.
Within the src folder, you’ll notice a file called App.js. This will be home base. Everything that we want rendered on our page will live here. Below is the default App.js, which we’ll change to make our own:
Make a Plan
Before we jump right into writing code, we should decide what our app looks like to help us break down our code into those components we talked about. Our app might look like:
According to this sketch, here’s one way we can structure our app:
- Header component — to include our title (and a description if we’d like)
- NewTaskForm component — a form that allows users to add new tasks (building this will come in a future post)
- TaskList component— a collection of tasks
- Task component— an individual task
We will need to create a separate .js file for each of these.
Before we do so, let’s create a data file with a few to-do items that we would like to render on the page when it is loaded.
Define Initial To-Dos
Within the src folder, create a file called todosData.js. Similar to how we may create a db.json file for a Vanilla JavaScript app, let’s create an array with to-do objects. These can be fairly simple, with only two properties: an id, and the text that describes the task. We’ll need access to this data later, so let’s be sure to export our array as above.
Create the Header
Now let’s build the app! First thing is first, we need a title. To get that set up and organized, let’s create a components folder within our src folder. This folder will house the components we previously defined. Within components, let’s create a Header.js file.
For this project, we will always set up our components by:
- importing React
- creating a function with the same name as the file component that will return JSX *In React, it is standard for components to begin with a capital letter, which differs from functions in vanilla JavaScript
- exporting the function This will allow us to import the new component and use it in our App.js, which will render it to the browser
In our Header.js file, let’s start simple and return an
element with our title.
If you save and head over to your browser window, you’ll see that nothing has happened quite yet. That’s because we haven’t added this Header to our App.
Let’s got into App.js and give it access to our new Header file. To do so, we must add an import statement to the top of App, as below:
import Header from ‘./components/Header’;
Once that is done, we can use
If you take a look at your app in the browser, you should now see “My To Do List” at the top.
Define a Basic To-Do
Now let’s work on rendering a to-do on the page. We know that we’ll need to pass data in from our data file (ahem, perhaps using props) to create the to-dos we previously defined, but we can build a skeleton for what each to-do will look like now.
Let’s create a new file called Task.js in our components folder. We’ll set it up as we did our Header and customize.
We know we will want to display the to-do item, along with a button to mark the task as done. (We will add functionality to the button in a future post)
With the Task component defined, we can now work on creating our collection of tasks.
Create Our List
Let’s create a file called TaskList for this component.
Of course, our list is going to be a series of Tasks, so we have to import the Task component into our TaskList for use. For now, let’s start with adding a single Task just to see it rendered to the page.
Remember that we still have to import this to our App component. Let’s go ahead and do that as below.
If you take a look at the browser now, you’ll see our title, and a single todo.
Now that we see our components working together, let’s work on getting our actual to-dos from our data file on the page.
To pass down information from our App to our TaskList, we’ll have to pass them in as props. We can do this by adding a property and value inside of our
Now over in TaskList.js, we’ll have to pass our props as our argument to pull that data through. We can either pass in as “props” and then refer to our data as “props.todos” within our component, or we can destructure our props as “{ todos }” (as we would any object) to simply refer to the data as “todos”. I selected destructuring in my example.
We’ll now have access to our todosData file in our TaskList component.
Okay, we know that we are going to want a Task component for each item in our todos. Let’s use map to accomplish this.
Remember that when we want to code in JavaScript within our components’ return statements, we must use { }.
To use map on an array, React wants us to give each result a unique key. We added unique IDs to each item in our list, so IDs will work perfectly as keys.
When you open the browser, you should now see three to-dos. Great!
Next, let’s get those three items to display our real to-do text.
Similar to how we passed our todos down to TaskList, we’ll want to pass a single to-do object to each Task. We already have a map that can help us with this, so we’ll just add a “todo” prop to our
Update Tasks With Information
Back in our Task.js, we can’t forget to add the as a parameter for our Task below. Now we’ll have access to our to-do object, and can access the text to add within our
as below.
Conclusion
Now when you open your browser, you should see a title, and three to-dos. Nice work!
In Part II of this post, we review state as we build events that allow the user to add a new to-do and delete a completed to-do
https://medium.com/geekculture/build-a-basic-app-in-react-part-ii-c70e10f7e850
Build a Basic App in React, Part II
Natalie BarbaFollow
Sep 20 · 7 min read
It’s time to go over React state and incorporate it into the to-do app we’re building. If you haven’t already, be sure to check out Part I of this post which reviews React components and props as we begin to build this app.
Now onto state.
Quick Overview
So what is state? In React, state is dynamic data that changes as users interact with your application. The fact that state can change during a component’s lifetime makes it different from props — props rely on parent components to pass static information down to their children.
Note that in order to work with state in your code, you must import the React useState Hook. Now what is a Hook? React documentation describes it best. It’s “a special function that lets you ‘hook into’ React features.” For example, useState is a feature that was built for React class components. We are building our app using functional components, which don’t include the same features, but we can import the features we need, like useState, with a Hook . To learn more, be sure to check out the documentation.
Implementing useState looks as below:
import React, { useState } from ‘react’;
function Example() { // Declare a new state variable, which we’ll call “count” const [count, setCount] = useState(0); … }
On the left, we have two variables. First we have our state variable and second our setter function which updates our state. On the right, we set our state variable to an initial value that we decide. So for the example above, we initially set count to 0. Later, we can say setCount(5) to update that count to 5. We’ll see more examples in our code-along. Let’s get started.
Goals
We will add two key features to our to-do app:
- The ability to mark a task as complete, or “Done”, and remove it from our task list.
- The ability to add a new task
We will accomplish both by using state.
Planning Where State Lives
As we think through how we can accomplish our goals, we should ask ourselves, do we need to manipulate data? If so, which data?
Whether we’d like to delete an existing task or add a new one, we will need to manipulate the array that we iterate over in order to render each to-do element on the page.
We would like to change data according to user actions, within our component’s life. Sounds like state. Where should this state live? These four questions help us decide:
- Identify every component that renders something based on that piece of state
- Find a common owner component (a single component all components that need that state in the component hierarchy)
- Either the common owner or another component higher up
- If you can’t find a component where it makes sense to own, need a new component
Both TaskList.js and NewTaskForm.js will need to use this array that is updated by user actions. Though we created a file for our NewTaskForm component, we haven’t built it nor imported it anywhere, so let’s take a moment and take care of that.
NewTaskForm.js
We can create a very simple form by adding an input area for the new task and adding a submit button as below
Now we must import this into our homebase, App.js.
App.js
We know that our NewTaskForm won’t need access to our previously built data, todos, so there is no need to pass in props quite yet.
Planning State Continued
Now that we’re set up with all of our components, we can go back and determine where our state will live — the state for our to-do array that we will manipulate through user actions. As we mentioned, both NewTaskForm.js and TaskList.js will need access to this array, so we’ll want our state to live in their shared parent component, App.js.
App.js
Remember, if we want to use state, we must import the useState hook. Afterward, let’s create a state variable for that array of to-dos we keep mentioning. We’ll set the initial value of that array as the array we’re importing from todosData.js.
Let’s tackle one user action at a time, starting with the “Done” button click.
We know that when we click “Done”, we will want to remove an element from todoArray. We must create a function that manages this logic, and any time we create a function to manage a state’s manipulation, we should do so within the same component as we have defined state.
Let’s create a function called deleteItem that will take itemToDelete as a parameter. We’ll create a copy of our original todoArray, minus the item we would like to delete using the filter method. We can assume that no two to-dos will be exactly the same and filter based on the to-do’s text description. Finally, we’ll use our setter function to update our todoArray to our updated array.
Now, instead of passing down the original dataset, todos, down to TaskList.js we’ll want to pass down the array that updates with user actions, todoArray. We will also want to pass down our newly defined deleteItem function so that (eventually) our event handler function can invoke it. Our updated App.js should be as below:
TaskList.js
Here, we’ll need to update our destructured props accordingly. We’ll also have to update the array that we are mapping over to create Task components for each to-do. We won’t use the deleteItem function here, so let’s also pass that down to our Task component.
Task.js
Back in Task.js, all we have to do is add a click event listener to our button, which will execute the deleteItem function. We can create an event handler function that calls that function as below.
Now if you refresh your app in the browser and click on any of the “Done” buttons, that should get rid of a task.
*Note the changes will not persist in the app upon refresh. For the changes to persist, there must be communication to a server, which is not covered in this blog post.
App.js
Because we’ll be adding a new task to the same array that we already have a state for, we don’t need to create a new state. Similar to how we created a function to handle deleting a task, let’s create one for adding a task, back in App.js where our state lives.
We’ll follow similar steps: create a new array, use the spread operator to create a copy of our original array, then add our new item to the end of it.
We’ll need to invoke this function when a user submits a new task, which will happen in NewTaskForm.js, so let’s pass it down as props.
NewTaskForm.js
Before jumping straight into the submit activity logic, let’s make our form a controlled form.
“In a controlled component, form data is handled by a React component. The alternative is uncontrolled components, where form data is handled by the DOM itself.”
We can do this by creating a state for our users input, after importing the useState Hook. Since todoArray is made up of to-do objects, we should follow that format and initialize our new state to an object with a “text” key and an empty string as its value. Let’s define our event handler function to update this state as the user types. As the last step, let’s add an onChange listener to our input text with this new function.
Now we can handle the submit.
Let’s create the function we’ll pass to our submit event listener. By default, a form submit refreshes our browser. We don’t want this, so we’ll start with preventing that default behavior. Next, we’ll add our state variable, which represents the object we created and updated based on the user’s input using state, to todoArray using the function we defined in App.js and passed down as props. Let’s reset our state and form to have empty values. Finally, we need to create an onSubmit event listener, using our newly created function as below.
Conclusion
You should now be able to open this up in your browser and be able to:
- See a title, a form, and a list of to-dos with buttons
- Remove to-dos by clicking “Done”
- Add new to-dos using the form
Nice work building an interactive React app and thanks for following along!