Use React Context to Manage Application State Through Routes

Share this video with your friends

Send Tweet

We’ll create a Router component that will wrap our application and manage all URL related state. We’ll see how we can use React’s built in context mechanism to pass data and functions between components without having to pass props all the way down through the component tree.

Marko
Marko
~ 8 years ago

Quote from the Facebook page: "If you want your application to be stable, don't use context. It is an experimental API and it is likely to break in future releases of React." (https://facebook.github.io/react/docs/context.html)

Should we be concerned?

Andy Van Slaars
Andy Van Slaars(instructor)
~ 8 years ago

I wouldn't be. This code could be updated to pass that same information down through the entire component tree via props. Also, if you're building anything with more routing functionality, you'll likely want to pull in something like react-router, which also uses context. I'm sure if the API breaks in the future, there will be some alternative, or it will be reasonable to update existing code.

gitnicos
gitnicos
~ 8 years ago

Quite honestly, I am a bit confused. On the one hand we are in for pure functions use as much as possible and by all cost have to avoid reliance on the global state, here though we are taking a context approach. I understand value of closures (function context) but static context could be single source of bugs. Also, is not it role of this.state to act as a reasonable single version of truth and state propagation with controlled boundaries? I guess I am saying I question if this is a "best practice" to stick to.

Andy Van Slaars
Andy Van Slaars(instructor)
~ 8 years ago

Context here is a convenience to avoid having to pass routing data down through the entire component tree as props, but if you prefer to avoid context, you can handle it via props from the top of the component tree.

In regards to having a single source of truth. The most important aspect to having a "single source of truth" is not that there is only one source for everything, but that each "fact" can only come from a single source. The trouble comes in when you have two sources for the same data. So if, for instance, I had exposed the route data via context and then assigned that value into some property on state in the top level App component, then there would be a risk in those getting out of sync. In this case, the state of the Router component is the source of truth for routing and is exposed via context just for convenience.

Hope this helps.

gitnicos
gitnicos
~ 8 years ago

Totally! It dawned on me that since this is a "special case" of using "context" in context of router, which by definition is supposed to be a "state" change coordinator, hence wrapping the the App component itself. Makes sense. Thanks again for eloquent explanation, Andrew!

Hector Pacheco
Hector Pacheco
~ 8 years ago

I have been using the es6 instead of es7, and I have gotten stuck on this lesson, I can't see to create the context to satisfied es6, I have followed a few suggestions found on the net. any suggestions here is my code import React,{Component} from 'react'

const getCurrentPath = () => { const path = document.location.pathname return path.substring(path.lastIndexOf('/')) } export class Router extends Component{

constructor(){
    super()
    this.state = {
        route: getCurrentPath()
    }
    this.handleLinkClick = this.handleLinkClick.bind(this)
    this.getChildContext = this.getChildContext.bind(this)
    this.childContextTypes = {
        route: React.PropTypes.string,
        linkHandler: React.PropTypes.func
    }
}

handleLinkClick(route){
    this.state({route})
    history.pushState(null,'',route)
}



getChildContext(){
    return {
        route: this.state.route,
        linkHandler: this.handleLinkClick
    }
}


render(){
    return <div>{this.props.children}</div>
}
Andy Van Slaars
Andy Van Slaars(instructor)
~ 8 years ago

Hector,

It looks like the problem is that you're defining childContextTypes on the class instance by using this, but that needs to be static. You can use the static keyword with ES6 class like in the repo for the lesson:

https://github.com/avanslaars/egghead_react_todo_app_course/blob/lesson_17/src/components/router/Router.js#L18-L21

Or you can attach them to the class outside of the class definition like

Router.childContextTypes = {
        route: React.PropTypes.string,
        linkHandler: React.PropTypes.func
    }

Hope this gets everything working for you.

Caden Albaugh
Caden Albaugh
~ 8 years ago

This question should've been asked way earlier in the series and I'm sure has a very simple answer but here goes. How are you able to not use any semicolons in your code? It finally got to me enough to ask. Thanks.

Andy Van Slaars
Andy Van Slaars(instructor)
~ 8 years ago

Caden,

It's pretty simple. Semicolons are not required in JavaScript. There are a couple cases where you need them, but if you don't write code that runs into those edge cases, it's completely safe and valid.

You can read some more specifics here: regarding semicolons

There are even linting setups that specifically call for no semicolons, I like Standard

People tend to have very strong feelings about this, some love it, others hate it. I prefer to leave them out, but if I'm working on a team that prefers them, I will put them in.

Hope this helps!

Brian Jensen
Brian Jensen
~ 8 years ago

Like the previous lesson this also fails to compile due to the use of history.pushState

Andy Van Slaars
Andy Van Slaars(instructor)
~ 8 years ago

Andrew Van Slaars 14 minutes ago Brian,

Just like the previous video, this is a linting error caused by some updated lint config.

You should be able to get everything working again by referencing history directly from window with window.history. You could also disable linting for that line by adding // eslint-disable-line to the end of the offending line.

You could also use the same version of react scripts as the video if you would prefer to not apply these workarounds while following along with the videos.

Hope this helps.

Buzwe Mfaca
Buzwe Mfaca
~ 7 years ago

Andrew

I don't what I'm doing wrong, when the app finish loading the All(link) becomes bold but when I click on other links nothing happens. I watched the video three time and also read transcript but no luck.

Code: https://github.com/BuzweMfaca/todo_react

Buzwe Mfaca
Buzwe Mfaca
~ 7 years ago

Andrew

I'm not sure what I'm going but my links are not working, when I click url just append # code: https://github.com/BuzweMfaca/todo_react

Buzwe Mfaca
Buzwe Mfaca
~ 7 years ago

Andrew

I'm not sure what I'm going but my links are not working, when I click url just append # code: https://github.com/BuzweMfaca/todo_react

Buzwe Mfaca
Buzwe Mfaca
~ 7 years ago

Andrew I'm not sure what I'm going but my links are not working, when I click url just append # code: https://github.com/BuzweMfaca/todo_react

Buzwe Mfaca
Buzwe Mfaca
~ 7 years ago

Andrew I'm not sure what I'm going but my links are not working, when I click url just append # code: https://github.com/BuzweMfaca/todo_react referring to https://egghead.io/lessons/react-use-react-context-to-manage-application-state-through-routes

max nynd
max nynd
~ 7 years ago

Hi Andrew, does React context work like the provider in react-redux?

isOst
isOst
~ 7 years ago

Hello, what should I do with this https://prnt.sc/iw75ee

In Link.js I've changed contextTypes to childContextTypes.