Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The context `router` is marked as required in `Link`, but its value is `undefined`

I have a problem with Link. Googled a lot of topics, but I did not get a correct answer. In one discussion, the problem is in the earlier version of the router, in the other in the wrong import of components, in the third the answer was not even announced.

Also, what's with the 'history'?

Versions of the components:

"react": "^15.4",
"react-dom": "^15.4",
"react-router": "^4.1.1",
"react-router-dom": "^4.1.1"

Errors are:

Warning: Failed context type: The context `router` is marked as required in `Link`,
but its value is `undefined`.

and

Uncaught TypeError: Cannot read property 'history' of undefined

The component where Link is used is quite primitive:

import React from 'react';
import { Link } from 'react-router-dom';

export default class Menu extends React.Component {

constructor(props) {
    super(props);
}

render() {
   return (
   <div>
        <ul>
            <li><Link to="/one">1</Link></li>
            <li><Link to="/two">2</Link></li>
            <li><Link to="/three">3</Link></li>
            <li><Link to="/four">4</Link></li>
        </ul>
    </div>
);
}
}

So the component with the router looks like:

import React from 'react';
import { BrowserRouter, Route } from 'react-router-dom'

import Page1 from './Page1';
import Page2 from './Page2';
import Page3 from './Page3';
import Page4 from './Page4';

export default class Routes extends React.Component {

constructor(props) {
    super(props);
}
render() {
    return (
    <BrowserRouter text = {this.props.text}>
        <Route path = "/one"
               render={(props) => (
               <Page1 text = {this.props.text.Page1} {...props} />)} />
        <Route path = "/two"
               render={(props) => (
               <Page2 text = {this.props.text.Page2} {...props} />)} />
        <Route path = "/three"
               render={(props) => (
               <Page3 text = {this.props.text.Page3} {...props} />)} />
        <Route path = "/four"
               render={(props) => (
               <Page4 text = {this.props.text.Page4} {...props} />)} />
    </BrowserRouter>
);
}
}

And the most root component of the App:

import Header from './pages/menu/Header';
import Routes from './Routes';

const texts = require('text.json');
sessionStorage.setItem('lang','UA');

export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
    text: texts.UA
};
this.langHandler = this.langHandler.bind(this);
}

langHandler() {
if (sessionStorage.lang === 'UA') {
    sessionStorage.setItem('lang','RU');
    this.setState({ text: texts.RU })
} else {
    sessionStorage.setItem('lang','UA');
    this.setState({ text: texts.UA })
}
}

render() {
    return (
        <div id="content">
            <Header changeLang = {this.langHandler} 
                    text = {this.state.text.header}/>
            <Routes text = {this.state.text}/>
        </div>
    );
}
}  

In short, the point is that the page always has a rendered Header, and below it, depending on the selected menu item, the corresponding component was rendered.

I will be grateful for any advice.

like image 343
Nevolgograd Avatar asked Jun 12 '17 12:06

Nevolgograd


2 Answers

We presume, that we have the following:

import  { BrowserRouter as StaticRouter, Router, Switch, Route, Link } from 'react-router-dom';
import  createBrowserHistory from 'history/createBrowserHistory';
const   customHistory = createBrowserHistory();

Then, it looks like that it is necessary to wrap every nested block of links with

<Router history={customHistory}>
    <div>
        <Link to={'/.../' + linkName1}>
            {itemName1}
        </Link>
        <Link to={'/.../' + linkName2}>
            {itemName2}
        </Link>
    </div>
</Router>
like image 144
Roman Avatar answered Nov 04 '22 03:11

Roman


You should use <Link> only inside the <Router> tag; if it's outside of it, you will get this error.

 const Links =()=>(
  <nav>
    <Link to="/">Home</Link>
    <Link to="/about">About</Link>
  </nav>  
)

const App=()=>(

          <Links/>  <==== this will throw Error
          <Router>
            <div>
              <Route path="/" component={Home} />
              <Route path="/" component={About} />
           </div>
        </Router>


    )

following is the right way...

const Links =()=>(
  <nav>
    <Link to="/">Home</Link>
    <Link to="/about">About</Link>
  </nav>  
)

const App=()=>(


          <Router>
           <div>
          <Links/>  <==== this will through Error
              <Route path="/" component={Home} />
              <Route path="/" component={About} />
               </div>
        </Router>


    )
like image 29
Ignatius Andrew Avatar answered Nov 04 '22 03:11

Ignatius Andrew