Class Based Components and Axios in React

So far we've been using functional components in React. These are what you'll want to use unless you need to either use state or lifecycle methods.

If you need to use either of these React tools (state or lifecycle methods), then you'll want to use a class based component.


Class based components

Instead of writing your component file like this:

import React from "react";

function Card(props){  
    return <div>jsx</div>
}

export default Card;  

We will make it a class, like this:

import React from 'react'

class Card extends React.Component {  
  render () {
    return <div>jsx</div>
  }
}

export default Card;  

Looks at the similarities and differences.

We need to extent the Component class that comes from React. Component has a few useful methods that we want to utilize. One that we need is render.

Look up at the render method in the above code and try to figure out what it's doing.

render will run every time that this components renders, or re-renders.


componentDidMount()

componentDidMount() is a lifecycle method.

For an in depth look at lifecycle methods, check out this article. For now, all you need to know is that your component has a lifecycle. It prepares to mount, it mounts, it updates, and eventually it unmounts.

We need to utilize the method componentDidMount() from the React.Component class because this is the ideal time make our axios calls.

We would use it like this:

import React from 'react'

class Card extends React.Component {  
    componentDidMount() {
        //cool code. 
    }

    render () {
        return <div>jsx</div>
    }
}

export default Card;  
Axios in React Components.

Buckle up, things are about to get heavy.

Imagine we have two components. <TodoList />, child of <App />. And <TodoComponent />, child of <TodoList />, grandchild of <App />

Try to build this^^ yourself, but if you get super stuck, you may use the following as an aid

//App.js
import React from "react";  
import TodoList from "./components/TodoList";

function App(){  
    return (
        <div>
            <TodoList/>
        </div>
    )
}

export default App  
//TodoList.js
import React from "react";  
import TodoComponent from "./TodoComponent"

function TodoList(props){  
    return listOfTodosThatWeAreGoingToBuildWithMap
}

export default TodoList;  
//TodoComponent.js
import React from "react";

function TodoComponent(props){  
    return (
        <div>
            <h1>{props.title}</h1>
            <h2>{props.description}</h2>
            <p>{props.price}</p>
        </div>
    )
}

export default TodoComponent  

We want our TodoList components to use axios to get our array of todo's when the componentDidMount. To do this, we need to change it to a class based components.

Again, the only way you're going to learn this, is if you try it yourself. Go ahead and change your TodoList component to class based. After that, use that componentDidMount method. If you need some help, you can use the following:

//TodoList.js
import React from "react";  
import TodoComponent from "./TodoComponent"

class TodoList extends React.Component{  
    render(){
        return listOfTodosThatWeAreGoingToBuildWithMap
    }
}

export default TodoList;  

Alright. We've laid a great foundation. We now need to use Axios to give us an array, and we need to use that array to build our listOfTodos. This list will be an array of TodoComponents with unique props.

First, let's make an API call in componentDidMount. Try it by yourself. Remember that it's an npm package. So, do the stuff that you need to for npm packages. Also, here is a hint if you've forgotten some of the syntax.

axious.get(url).then()  

Give it some attempts. If you can quite get it, here it is in all it's glory:

```js
//TodoList.js
import React from "react";  
import TodoComponent from "./TodoComponent";  
import axios from "axios";

class TodoList extends React.Component{  
    componentDidMount(){
        axios.get("https://api.vschool.io/ericnatejones/todo/").then((response)=>{
            console.log(response.data);
        })
    }
    render(){
        return listOfTodosThatWeAreGoingToBuildWithMap
    }
}

export default TodoList;  

This should console.log our array of todos. Feel free to use your own todos if you're familiar with this cool api.

We will now have a very very brief intro to state


state

props are data that are passed down from a parent and don't change once a components renders

state is data that can update.

The reason we need to talk about state, is that we will have an array that starts off empty. In this case, let's call it todos.

We will make a call to an api, while that is happening (asynchronously) our component will render. As the data comes in, our array will change. It will be populated, and our user can then see the data. Because our data is changing, we will need to use state.

Go ahead and throw this constructor method into your Class based component.

constructor() {  
        super();
        this.state = {
            todos: []
        }

    }

There are a few new things here. We need to call super() to get state from React.Component. We'll talk about it more later, but for now, you don't even need to know that, all you need to know is that you need to call it.

this.state = {} is how we define all the data that we foresee needing to be updated. In this case, our todos Array.


.map()

In our render method, let's map over this array (it hasn't been populated) but hopefully we can get our app to not have any errors. Try this one your own. Struggle with it! If you want to test it, you can add an item or two to your state array.

constructor(){  
        super()
        this.state = {
            todos: [
              {
                title: "Get milk",
                description:"2%",
                price: "$1.50"
              },
              {
                title: "Fire Subordinate",
                description:"Let them down gently",
                price: "$1.50"
              }
            ]
        }
    }

Once that's working, we only need to update state after our API does its thing!!!


setState()

We will use this.setState() to change our state.

setState() takes a function, and that function needs to return our new state.

It looks like this:

this.setState(()=>{  
    return {
        todos: response.data
    }
})

We are going to learn more about setState, and state in general, but for now this is all you need to know


Do not use unless you have tried for a long long time to figure out the bugs and moving parts on your own.


All code for our TodoList.js below

import React from "react";  
import TodoComponent from "./TodoComponent";

import axios from "axios";

class TodoList extends React.Component{  
    constructor(){
        super()
        this.state = {
            todos: []
        }
    }


    componentDidMount(){
        axios.get("https://api.vschool.io/ericnatejones/todo/").then((response)=>{
            this.setState(()=>{
               return {
                 todos: response.data
               }
            })
        })
    }

    render(){
        let mappedTodos = this.state.todos.map((todo)=>{
          return <TodoComponent title={todo.title}
                       description={todo.description}
                       price={todo.price}
                       />
        })

        return mappedTodos;
    }
}

export default TodoList;