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.
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>
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>
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With