Building a todos application by following these order:
1 Create the React app on the terminal. Run the command below and it will create a directory
npx create-react-app app-frontend
2 Start up the React app
Change directory to
app-frontend and run
npm start . This will open the HTML page
App.jsis under the folder
src . This defaults to HTML code and it is rendered on the homepage.
App.js presents as the highest level component in the React app structure.
index.jsholds the application’s configuration and dependencies.
3 Set up a component structure
Component structure for todo-app.
App -> (Nav, MainContainer)
MainContainer ->( CreateCard, ToDoCardContainer)
ToDoCardContainer -> ToDoCard
ToDoCard -> ToDoList
We can write components with JavaScrip functions or classes. There are separate folders in the application which are components and containers.
4 Set up the back end using Rails API
We create Card and List models. Cards have many List and List belong to a Card (has many belong to relationship). Using these command lines.
rails new app-api --api
rails g resource card title --no-test-framework
rails g resource list description completed:boolean card:references --no-test-framework
This will create Card and List models in back-end structure without test_unit by using
We need to install
rack-cors (middleware for handling cross-origin resource sharing)
active-model-serializer if you are using it to organize your JSON data. Add these gem to the
Gemfile and run
bundle install in the terminal.
5. App component
App is the highest level which renders
Nav children components using JSX (JavasScript Extension). We import components and export App to
index.js which will render the entire application
6 Nav component
We use the function component to display a sample_logo in
7 CreateCard component (controlled form)
MainContainer will be a class component that will hold the logic and state for the application which will be passed down as props to the children components. The
MainContainer will fetch request to the back end retrieve created cards, and pass down the cards to
TodoContainer to be rendered.
CreateCard the component will render a form that will take user input and sent it to the back end to create a new instance of
We will use controlled forms (React component handles the form data) instead of uncontrolled forms (DOM handles the data). The component will render the form and hold its own state to keep track of the change of input. The input will be saved inside the component’s state. The
CreateCard component’s state will be updated when input is changed.
state to an empty string and
handleInput function inside the class to handle the changes from the input. The properties of the event only exist when the callback is active. The
event.persist() references the event and get value and methods inside the function. The
event.target.value contains the user’s input value inside the form and
this.setState will store that value. The
handleInput function will reset the state of the
CreateCard component when the input is changed in the form. This function is called by the event listener
onChange inside of the rendered form by using
this keyword (prefer to parent class which is CreateCard.
We pass the input from
CreateCardcomponent to the back end to create an
Card instance and adding this new card to be rendered under
MainContainer will be the parent component of
MainComponent renders all the cards from the back end on the page. We set the state as an empty array of cards.
crateNewCard function that will pass down as a prop to the
CreateCard component. This function fetches input to the back end and receiving the newly created card object and adding the object to the cards array inside the state.
We pass the reference to
this function as a prop to the
CreateCard component when a user submits the form.
handleNewCard function to prevent the default action of a submit button and call
CreateCard component. We can access the props by using
this.props for class components. We pass down props as the function’s argument.
9. Fetching data from the back end
MainContainder renders the
ToDoCardContainer will render each
ToDoCard components. We send a fetch request to the back end to get all existing cards. This is asynchronous. It will fail to load and error if we try to render the cards before the fetch request is completed. Therefore we will use the
componentDidMount to run an asynchronous after the initial render of the page. When the fetch request is finished the
this.setState will be called and re-render the page with data returned from the fetch request.
We will save all the cards instances to the
MainContainer state. Then we pass it down to
ToDoCardContainer as a prop.
ToDoCardContainer component render all the
ToDoCard components. We will use the function component. We map over
ToDoCard component for each card object. The
ToDoCard component will take card object as the prop which contains title of the card and the todos list. We pass down a unquie card id to kee tract
We render new created cards on the page. We return a
div container the card object’s tile in
ToDoCard with props was passed down from
We add controlled form on each card to allow the user to add a list item(s) per card. The input state is in
TodDoCard the submit function will be passed from the
MainContainer. The controlled form is created inside
addList callback function creates a new
List instance using the input and associated card id. We will add new list object to the appropriate card’s array of the list inside the
cards state. We find the associated card using the returned list object’s
card_id. We concatenate the new list object onto the existing lists array for that card. We map over the existing cards array stored in the state to replace the card object in the with the new, updated card object with the additional list item. We
setState of the cards to the new cards array.
12 To DoList
We render list per card. We map over the lists for each card which was passed down as a prop to render a
ToDoList component. The list item has attribute
complete which as set to false by default and set to true when the item is clicked on.
13. Checking off a list item
Ther user can click on the list item and check off the completed list item.We change the List object attributes and keep track inside the
MainContainer's state. The function will take List ID and the Card Id as its arguments. We check if clicked list item’s attribute
complete to opposite. For example, change it to true if it’s false. We send new state to update by
We will update card’s state from the change by using the map method. The list is nested array within the state. We create a new array of updated list then update the card array.
handClickList function will be passed down as the prop to
ToDoContainer then to
ToDoCard, and last to
ToDoList component. Each
ToDoList component has the
handClickList function as its pro and call the function on each event.
h3 className value is change by using the ternary operator if list’s attribute is true or false.