endernet.io

Grabing an Advice Slip with React.js

☕️ 3 min read

Grabing an Advice Slip with React.js

Here is a demo of what we are going to create.

Some prerequisites you will need:

  • Node.js
  • NPM / Yarn (I will be using Yarn)

Creating our React Application

First we will need to create our app with the create-react-app command.

create-react-app advice-slip

Once your package manager finishes installing, cd into the new directory you just created and tell NPM/Yarn to run or start your application.

cd advice-slip
yarn start

Now the foundation of your app should be up and running!

We are going to use the existing css with the rotating image. I’m going to use this image of my head, but you’re free to use whatever image you want.

So we will first clean up the code until it looks like this.

import React, { Component } from "react";
import "./App.css";

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
        </header>
      </div>
    );
  }
}

export default App;

Let’s import our image to take the place of the React logo.

import avatar from "./avatar.png";

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={avatar} className="App-logo" alt="logo" />
        </header>
      </div>
    );
  }
}

Now that’s a good looking logo!

Next we will create a state for our advice slip, error catching, and loading screen.

constructor(props) {
  super(props);
  this.state = {
    error: null,
    isLoaded: false,
    advice: ""
  };
}

This is going to set our state, for now the advice object will be empty.

Let’s render the state and create an if statement for our loading screen. We will also add some HTML elements to give our app some context.

render() {
  const { error, isLoaded, advice } = this.state;
  if (error) {
    return <div>Error: {error.message}</div>;
  } else if (!isLoaded) {
    return <div>Loading...</div>;
  } else {
    return (
      <div className="App">
        <header className="App-header">
          <h2>Jordo's daily advice</h2>
          <img src={avatar} className="App-logo" alt="logo" />
          <p>Our advice will go here...</p>
          <h3>Now go forth and prosper!</h3>
        </header>
      </div>
    );
  }
}

Your app should be stuck on Loading… since we haven’t given it any reason not to.

You can find the documentation for the API we are using here.

Let’s change that by fetching the Advice Slip API and changing the state.

componentDidMount() {
  fetch("https://api.adviceslip.com/advice")
    .then(res => res.json())
    .then(
      data => {
        console.log(data.slip.advice);
        this.setState({
          isLoaded: true
        });
      },
      // Note: it's important to handle errors here
      // instead of a catch() block so that we don't swallow
      // exceptions from actual bugs in components.
      error => {
        this.setState({
          isLoaded: true,
          error
        });
      }
    );
}

Here we are only fetching the API when the app renders with componentDidMount(). Then we are taking that response and logging it to the console for now. We are also are changing the state of the isLoaded object to true, and returning any errors that we catch.

You can see our advice in the console:

Now let’s take that data we are logging in our .then() function and pass it to our state.

.then(
  data => {
    this.setState({
      isLoaded: true,
      advice: data.slip.advice
    });
  }

All that’s left is to load that object in our HTML element.

return (
  <div className="App">
    <header className="App-header">
      <h2>Jordo's daily advice</h2>
      <img src={avatar} className="App-logo" alt="logo" />
      <p>{advice}</p>
      <h3>Now go forth and prosper!</h3>
    </header>
  </div>
);

Success!

We can change the styling up a bit in our App.css file.

.App-header {
  background: rgb(135, 132, 204);
  background: linear-gradient(
    90deg,
    rgba(135, 132, 204, 1) 0%,
    rgba(135, 132, 204, 1) 35%,
    rgba(190, 222, 255, 1) 100%
  );
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white;
}

h2,
h3 {
  color: #ffdad7;
}

Here’s our finished product: