React Learnings from 2018 - Part 3: Props and Routing
Published: 2020-11-03 08:13:11

---
title: React Learnings from 2018 - Part 3: Props and Routing
published: true
description: Part of an old series of posts I wrote about getting to grips with React
tags: 
//cover_image: https://direct_url_to_image.jpg
---


In the last post we set up a bunch of components, now we need to look at how they can talk to each other. This relies on Props and State.

# Props

When you have an image tag you will use multiple attributes like: `<img class="etc" src="url" alt="something">` So that the image tag has the information it needs.

In React, **props** are those attributes, and a way to get data into that component. So if we want to pass data from App to Header we can do this via props.

In `header.js` we have the following snippet of code:

```js
<h3 className="tagline">
    <span>Great tasting stuff</span>
</h3>
```

If we want to pass in a new tagline from `App.js` we can change the Header component tag to include a prop:

`<Header tagline="Terrible Food" />`

If you now look in React Dev Tools you will see the tagline prop when you select Header.

### How do you use the prop?

```js
<h3 className="tagline">
    <span>{this.props.tagline}</span>
</h3>
```

**A component is an object**, so we can just pull information from the *props* object within it. JSX needs to use curly braces when we need to speak in pure JS by the way.

# Stateless Functional Components

I mentioned functional components in an earlier post. As a recap, if all a component is doing is rendering something then it doesnt need to have all the functionality of a class based component.

Don't use a sledgehammer when a regular one will do I guess. It is just a regular function, however `this` wont work the same way so we can just pass it to the function:

```jsx
const Header = props => (
    <span>{props.tagline}</span>
)
```

# React Router

Routing is all about pointing to certain urls with certain content. If you have used Express you may have already had experience in setting up a route to render a certain view for instance.

You need a router to do something depending on the URL the browser uses.

The routing doesn't come build into react, there are a couple of different routers out there. The two most popular are:

-React Router
-Next.js

We are using React Router for this example.

## Setting up the router

Since everything is a component in React, we need to set up a `Router.js` component

If you recall when we had a list of dependancies we had one called `react-router-dom` this is what we are going to use here. It has a number of components since it handles routing for React Native too.

For our purposes we need:

- BrowserRouter
- Switch
- Route

## Route

The route component takes in several props, the ones we most care about are:

`path` - This states the URL path this applies to (e.g "/")

`exact` - specifies that the path needs to be an exact match

`component` - What component to use, this needs {};



# Building our router component

First we import them: `{BrowserRouter, Route, Switch} from 'react-router-dom'`. We also need to import React for JSX.

Then lets build our router function, this can be a stateless functional component:

```js
const Router = () => (  {/* Clever way of returning */}
    <BrowserRouter>
        <Switch>
            <Route exact path="/" component={storePicker}/>
            <Route path="/store/:storeId" component={App}/>
            <Route component={NotFound}/> {/* Our 404 type page */}
        </Switch>
    </BrowserRouter>
)
```

At the end remember to:

1. Make sure you have imported any components you are routing to.
2. Add `export default Router` to export it!


When we are done, in our `app.js` lets import router by doing: ` import Router from "/.components/Router" ` Make sure to also use the Router tag in place of any placeholder you might use.

Create any new components you have made, such as the `NotFound` component.

You now should have a working router! Note that in the props, when we look at a component, we get some new props such `params` which is useful when it comes to routing.

## Sidenote : What is export default anyhow?

When we specify `export default <function>`, the corresponding `import` will take that function if we dont specify.

However we can have a file with a bunch of functions and pull out what we need with destructuring. For example if you have a `helpers.js` file with functions they can be exported with the export command:

    export function example(){
        return someFunctionality
    }

in the file we need the function we can import it:

`import { example } from "../helpers"`

**Random Note: use defaultValue when setting a default value on an input, as opposed to value. React doesnt like it otherwise**

## Conclusion 

We now can have a basic multipage react application with different components being loaded based on the URL via React Router

We can also pass values from the parent component to the children via Props

In the next section we delve into Events and how things can change based upon user input.


ChAPTER 21 - Events and Refs

Events are how React functions when something happens, such as a button being clicked or a form being submitted. They are used quite a bit in JS, you might know that.

One main difference in React is they are done inline:

`<button onClick={this.handleClick}>Click Me</button>`

Where handleClick is a function availble to the component. there are alot of 'on' events to choose from. Note you *do not* include paranthesis, else it will run on mount.

## Submitting a Form

Like the button, we include an event on the form tag:

`<form onSubmit={this.handleSubmit}>`

Let's assume the handleSubmit method is just a console.log("Hi") for now. We should expect 'Hi' right?

Nope, because **the default behavior is to refresh the page**

We can pass the `event` object to the method to allow handleSubmit to stop the refreshing behaviour with the following method:

`event.preventDefault();`

Now we will see the console.log as the page wont refresh.

## Taking an input and Routing based on that

In this example, let's assume we want a form that goes to a user profile based on an input's value. 

<form onSubmit={this.goToProfile}>

The method currently looks like this:

```js
goToProfile(event){
    event.preventDefault()

}
```

We need to do two things:

1. Get the text from the input
2. Change the page to  /profile/INPUTVALUE


## Getting the text from an input properly

We don't want to just pick it up from the DOM, the DOM should be result, not take part in performing a task. Well there is two ways we can do this. First is `state` which we will get to and generally is the prefered method, but another way is `refs` which we will use this time around.

## Refs

A ref, *references* a DOM element so a method can do things with it. This has had many forms over the years but this implementation is the most modern...at tiem of writing:


1. Add a prop on the input tag: `ref={this.myInput}`

2. Create a ref at the start of the component: `myInput = React.createRef();`


That's how we ref nowadaya. Now we can reference the dom node in any methods on the component. Yay!

Wait no we can't...just doing this within a method however will cause an error! It won't be able to find the 'this' that has myInput. This is quite wierd. `this` should be the component right?

## "this" and Binding Methods

Let's take a slight aside...

Well react has `binding methods`, these built-in methods bind this to the component, normally this is what we use.  However a component's own unique methods *dont have that binding by default because the components extend React.Component* This does not automagically pass to methods we make ourselves in a component.

A solution to this is to bind our own methods, there is two ways to do this:

A constructor function - hopefully you recall from ES6 classes we can make a constructor function and define our methods in there:

```js
constructor(){
    super();
    this.goToProfile = this.goToProfile.bind(this)
}
```

Wow that is confusing, but it makes sure that the goToProfile's 'this' is the 'this' of the constructor which is the component...ouch my poor head!

A new way (which is probably going to be old by the time you see it) is `changing the method to a property that is an arrow function`

Old Method: `goToProfile(event) {}`

New Property: `goToProfile = (event) => {};`

The arrow function binds `this`

In short, if you want to access `this` inside a custom method, turn it into a property with a fat arrow function. Something like this:

```js
nameRef = React.createRef();
createProfile = event => {
        event.preventDefault();
        const profile = {
            name: this.nameRef.value.value
            //Etc. Now nameRef can be picked up and used... why is it value value? Read on...
}
```

## getting a value from an input 

Now the component is capturing details about the input when there is a form submit via a ref.

When the goToProfile method is run, we have asked it to `console.log(this)`, the `this` here is the component. But we can drill deeper:

- `this.myInput` will return the reference
- `this.myInput.current` will return the input for which the ref was placed.
- `this.myInput.current.value` will return the value of the input

As you can see there is quite a few layers involved here! It's a good idea to put this into a variable when we use to to go to that URL.

## Change the URL without refreshing the page using Push State and React Router

Now we can access the data from the form submission we can use it to direct us to the relevent URL.

To do this we use a React Router method called `push`. We have access to React Router since StorePicker is a child of the Router component, so when we look in react dev tools we can see the props that are given by React Router. Push method is actually in an object called `history`, so the command we want is:

    this.props.history.push(`/profiles/${profileName}`)

Note the backticks, and dollar sign. We are using a template string here.

And success we will route to `/profiles/profileName` where profileName is the variable recording the value of the input which is the value of the ref which is on the component.... that simple!

Note how fast it is, react router just needs to swap out the component, and doesnt need to load the whole page. Thats pretty cool!