DEV Community

Joan Indiana Lyness
Joan Indiana Lyness

Posted on • Originally published at Medium on

Rails API Project Part 3: Adding a front end with React & Redux

and how to call the custom sorting methods we created on the back end.

In the previous post we covered how to finish setting up our Who’s Who Congress Rails API. Now we need a front end where we display all that awesome data in fun ways.

I built my front end with React and Redux.

What is React?

React logo

It’s a Javascript library that was created by Facebook. We use it to create modular user interfaces, where each thing we present on the page is a component. Each component has its own code, which makes it easy for teams to work on the code. Then based on what view you want to render, you can choose which components to display.

In my app, I have a SenateContainer component that has a child component called SenatorsList. SenatorsList in turn, has its own child component called SenatorCard. By the time I’m done with my project, SenatorCard will have its own components, like SocialMedia Links, etc.

Then, when I build my senate page, I simply load these building blocks into one file. Take a look at the picture at the top of this post. It includes many components: a Home Page component that includes a NavBar component (the four large buttons across the top of the screen); and the SenatorsList component which includes the sorting buttons, search bar and senators card.

Components can have state and methods, which they can pass down to their child components. React has methods for passing these things (props, short for properties) down to child components, but it can get cumbersome when your components have components that have components.

Enter: Redux

Redux is a tool for managing state. A list component’s state, for example, is which items are currently on the list. With Redux, workflow goes like this:

You have an object with an initial state. Let’s say you have a to-do list with no items in it. So List’s initial state is an empty array: [].

Your user clicks a button to add a to-do item.

When they submit the new item, the List component calls an action from a list of actions that live in a separate file.

A reducer sets a new state for the component based on the action. So if the action was add a to-do item, the reducer uses a spread operator to makes a copy of the current state (cardinal rule: never ever amend state, just make a copy and amend the copy) and add the newToDo.

function ListReducer(state = [], action) {
 switch(action.type) {
 case 'ADD\_TODO':
 // adds todo`
 return { ...state, newTodo }

Now, List’s state has been updated in the store. If this confuses you, you are not alone! Here is an excellent super-short primer called “Explain Redux Like I’m Five.”

So about that API call …

To set up our app to update with data from our API, we need to set an initial state for the component will hold our data. Let’s focus on our SenatorsList component, which I set up with an initial state of an empty array of senators.

And my view looks like this:

notice: no senators listed

When my user clicks the red ‘Senate’ button I want the page to load all 100 senators (which I formatted as flashcards, using React ui semantic).

I set up an event listener on the button so that when it is clicked, it will call an action from my Actions/senate file:

The action, fetchSenate() uses, the fetch method to call the API we set up earlier; put sthe response in JSON, and then tell the Reducer, hey Mr. Reducer, pls go ahead and dispatch the action with the type “SET_SENATE”, and feed it the data I just stored in the variable ‘senate’.

The reducer then updates the app’s state.senate with an array of 100 senators! This updated state lives in our store.

Back at the ranch …

Meanwhile, SenatorsList has no idea what’s going on. It sent off a request for senators, and 100 senators came back, but they came back to the store. To give SenatorsList access to its own state, we have to connect it to the store. We use Redux’s built-in ‘connect’ tool to do this:

At the bottom of our SenatorsList component:

Without Redux, we would normally have one line here: export default SenatorsList. But we’ve added more information here — before we export SenatorsList, we’re connecting it to the store, where we want it to grab its own state and its actions (the ones living in the actions/senate.js file).

The export line starts out like this:

export default SenatorsList connect()(SenatorsList)

Connect takes two arguments. The first is mapStateToProps, which lets the component (once it’s connected to the store), call its state as a prop (shot for property). Here’s what mapStateToProps looks like:

const mapStateToProps = state =\> ({senate: state.senate})

The above code says — go to the store, grab my state (state.senate) and from now on, let me access my state as this.props.senate.

But SenatorsList wants more than just its state. It also wants access to the actions in the store that change its state. Back to our connection:

The second argument connect takes is mapDispatchToProps. You can either write out the full method or add a list of the actions as a comma-separated list surrounded by curly braces. This says: while you’re at the store, grab these actions, and map those to props too, so I can call this.props.fetchSenate, etc.

Think of the connect, mapStateTo Props and mapDispatch to props as a way for your humble component to go to the store to get superpowers!

Now that SenatorsList knows its own state, it uses each senator’s information to render a SenatorCard, and then displays them in a grid.

Let’s pass our superpowers down to some other buttons.

My senate view includes five sorting buttons. Each one is tied to a custom sorting method that we defined in our Rails API, and to a search term that we can feed to our API to get back the list of sorted senators.

These buttons look a lot like the Senate button but they work a bit differently.

The Senate button doesn’t directly fire the fetch action. Instead, it routes the viewer to the Senate route, which mounts the SenateContainer component, which mounts the SenatorsList component, … which automatically fires the fetch action when it loads. In other words, when you click Senate, I want you to automatically see all 100 senators.

Now that you’re looking at all 100 senators, you have the choice of clicking one of the sorting buttons to re-sort the senators. Instead of mounting other components, I want these buttons to reshuffle the cards that are already on the page. So I want each button to call its corresponding action directly.

To do that, I have to give each button the power to call that action. We could make each button its own component and have it go to the store to fetch its action, but there’s an easier way. We can pass superpowers down from SenatorsList to its children, each of the buttons! Here’s what they look like:

inside the return method in SenatorsList

Since these Buttons are being rendered inside of the SenatorsList component, they are children of SenatorsList, and SenatorsList can give each one the power it needs to perform its mission. Let’s see, the ‘Loyalists’ button will need to access this.props.fetchLoyalist, ‘Mavericks’ will need this.props.fetchMavericks, etc.

Now, when each button is clicked, it will fire the action (stored in actions/senate.js), which in turn will tell the reducer which of its actions to fire …. then the reducer updates the store. Since SenatorsList can now access its state as props, it automatically updates to show its new state: a list of 100 senators sorted by (whichever button we clicked!)

Here’s what the Loyalists sort looks like:

If you’ve read this far, I hope this helped you understand React and Redux.

Here is a link to the repos for this project: Front end & theback-end Rails API.

Top comments (0)