reactjsreact-routerlocationstatereact-link

this.props.location.state is undefined in React Link Router


I've seen several of these questions on Stack Overflow, but none of the fixes seem to work. this.props.location.state always returns undefined. Here is my AppContainer, ExamplePageParent, and ExamplePage.

import {Router, Route, Switch} from "react-router-dom";

class AppContainer extends Component {
  render() {
    return (
      <Router>
        <Switch>   
          <Route exact path="/page" component={Page}
          <Route exact path="/examplePage" component={ExamplePage}/>
        </Switch>
      </Router>
    )
  }
}
//has mapStateToProps and mapDispatch to Props here

export default connect(mapStateToProps, mapDispatchToProps)(AppContainer);

--

class Page extends Component {

  render() {
   return(
     <AnotherPage key=this.props.id>
   );
  }
    }

// has mapStateToProps here (this.props.id comes from here)

export default connect(mapStateToProps, mapDispatchToProps)(Page);

--

class AnotherPage extends Component {

  render() {
   return(
     <ExamplePageParent key=this.props.id>
   );
  }
    }

// has mapStateToProps here (this.props.id comes from here)

export default connect(mapStateToProps, null)(AnotherPage);

--

class ExamplePageParent extends Component {

  //pathName and dataPassed content filled, not relevant to question

  render() {
   return(
     <Link
       class={'link-styling'}
       target="_blank"
       rel="noreferrer"
       to={{pathname: this.state.pathName, state: {dataPassed: true} }}
     >
       Click Me
     </Link>
   );
  }
    }

//has mapStateToProps here

export default connect(mapStateToProps, null)(ExamplePageParent);

--

import {withRouter} from "react-router";

class ExamplePage extends Component {

  constructor(props) {
    super(props);

    //this has content:
    console.log(this.props.location);

    //undefined:
    console.log(this.props.location.state);
  }

  render() {
   return(
     // do stuff
   );
  }
}
export default withRouter(ExamplePage);

Solution

  • Issues

    To address the undefined location you have a couple options:

    1. Import a custom history creator from the history package:

      import { createBrowserHistory } from 'history';
      
      const history = createBrowserHistory();
      
      ...
      
      <Router history={history}>
        ...
      </Router>
      
    2. Use one of the higer-level routers, i.e. BrowserRouter, HashRouter, MemoryRouter, etc...:

      import { BrowserRouter as Router } from 'react-router-dom';
      
      ...
      
      <Router>
        ...
      </Router>
      

    To address accessing the "state" in the receiving component you'll need to add a bit of logic. When the app is started in a new window/tab the state isn't transferred, so to combat this you can send the route state serialized as a queryString search param.

    <Link
      className={"link-styling"}
      target="_blank"
      rel="noreferrer"
      to={{
        pathname: this.state.pathName,
        search:
          "stuff=content&moreStuff=moreContent" + // existing search params
          "&dataPassed=This is the passed data.", // additional for state
        state: { dataPassed: "This is the passed data." }
      }}
    >
      Click Me
    </Link>
    

    And then in ExamplePage process the queryString to extract and delete the added "dataPassed" query param, and redirect with populated route state previously existing queryString.

    class ExamplePage extends Component {
      componentDidMount() {
        const { history, location } = this.props;
        const { pathname, state, search } = location;
    
        console.log({ location });
    
        const searchParams = new URLSearchParams(search);
        let dataPassed;
    
        if (searchParams.has("dataPassed")) {
          dataPassed = searchParams.get("dataPassed");
          searchParams.delete("dataPassed");
        }
        history.replace({
          pathname,
          search: searchParams.toString(),
          state: { dataPassed }
        });
      }
    
      render() {
        return (
          ...
        );
      }
    }
    

    Edit this-props-location-state-is-undefined-in-react-link-router