react-router v4 alpha7 +dom6 not pushing context through BrowserRouter - react-router

With react-router v4 alpha7 and dom alpha6 (latest versions) i get the following error:
Warning: Failed context type: The context `router` is marked as required in `Link`, but its value is `undefined`.
in Link (created by MainComponent)
in p (created by MainComponent)
in div (created by MainComponent)
in MainComponent (created by Route)
in Route
in div
in Router (created by BrowserRouter)
in BrowserRouter
in ApolloProvider
I have seen similar questions like this, but i followed their advice.
BrowserRouter is a top level component around router components
import React from 'react'
import ReactDOM from 'react-dom'
import ApolloClient, { createNetworkInterface } from 'apollo-client';
import { ApolloProvider } from 'react-apollo';
import MainComponent from './components/main.jsx';
import AboutComponent from './components/about.jsx';
import { BrowserRouter, Route, Link } from 'react-router-dom'
const client = new ApolloClient({
networkInterface: createNetworkInterface({ uri: 'http://app.local:8001/graphql' }),
});
ReactDOM.render(
<ApolloProvider client={client}>
<BrowserRouter>
<div>
<Route exactly path="/" component={MainComponent} />
<Route path="/about" component={AboutComponent} />
</div>
</BrowserRouter>
</ApolloProvider>,
document.getElementById('tourapp')
)
Then there is the main.jsx:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
class MainComponent extends Component {
render() {
return <div>
<h1>Hello World</h1>
<p><Link to="/about">About</Link></p>
</div>;
}
}
export default MainComponent
Does anyone have an idea why the router context is not passed? This is almost straightfoward from the docs.

Do this, the link has to be inside the Router tag
<div>
<nav className="navbar navbar-default">
<div className="container-fluid">
<div className="navbar-header">
<a className="navbar-brand" href="#">WebSiteName</a>
</div>
<ul className="nav navbar-nav">
<li className="active"><Link to="/">Home</Link></li>
<li><Link to='/about'>About</Link></li>
</ul>
</div>
</nav>
<Switch>
<Route exact path="/" component={Weather}/>
<Route path="/about" component={About}/>
</Switch>
</div>
</Router>

Related

React Link not automatically updating page content?

While clicking on the links updates the slug, I have to manually refresh the page in order to get the page content to update.
app.js:
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import NavigationContainer from './titlebar';
import AllLinks from './all-links';
import Home from './home';
export default class App extends Component {
render() {
return (
<div className='app'>
<NavigationContainer />
<Router>
<Switch>
<Route path="/all-links" component={AllLinks} />
<Route exact path="/" component={Home} />
</Switch>
</Router>
</div>
);
}
}
titlebar.js:
import React, { Component } from "react";
import { NavLink } from "react-router-dom";
export default class NavigationContainer extends Component {
render() {
return (
<div className="navigation-container">
<div className="text-wrapper">
<div className="nav-left">
<NavLink exact to="/">
Redis Link Shortener
</NavLink>
</div>
<div className="nav-right">
<NavLink to="/all-links" >
All Links
</NavLink>
</div>
</div>
</div>
)
}
}
I've tried going through documentation, going through similar questions, and going through code I've written in the past that does work in this regard. As far as I can tell, what I'm using is identical to code I've written in the past that has worked. I'm completely stuck for why it isn't automatically rendering.

Local page links (<a href='#' />) aren't working with HashRouter

I wanted to add multiple pages to my React website so I started using the HashRouter import from react-router-dom. Since then only my main page loads and I am no longer able to use local links in the page. I can't redirect the user to specific areas on the main page which i used to be able to do before I started using the Router import. This website also uses github pages if that affects anything.
I am currently using the <a> tags like this:
<a className="nav-link" href="/#about-me">
About Me
</a>
with the URL appearing as this with no content below it
http://localhost:3000/#about-me
I have also tried using the <Link> tag but it just ends up reloading the page.
<Link className="nav-link" to="/#about-me">
About Me
</Link>
With this URL appearing instead:
http://localhost:3000/#/#about-me
How do I get my page to scroll down to the id rather than reload or load a blank page?
Main code snippets for reference:
Home.js snippet
const Home = () => {
return (
<div className='main'>
<section className='section-welcome'>
<Introduction />
</section>
<section id='about-me' className='section-about-me'>
<AboutMe />
</section>
</div>
);
};
export default Home;
Main.js
import React from 'react';
import { Routes, Route } from 'react-router-dom';
import Home from './Pages/Home.js';
import NoPage from './Pages/NoPage.js';
const Main = () => {
return (
<Routes>
<Route path='/' element={<Home />}></Route>
<Route path="*" element={<NoPage />} />
</Routes>
);
}
export default Main;
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { HashRouter as Router } from 'react-router-dom';
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Router>
<App /> {/* The various pages will be displayed by the `Main` component. */}
</Router>
</React.StrictMode>
);
The problem is with how the code runs with GitHub pages, not the references.
Currently, whenever a link is clicked in the NavBar the website tries to load the URL as root/{href from <a> tag}. This conflicts with GitHub pages as it searches links under the githubname.github.io/project-name/ and the program is trying to display githubname.github.io/#.
In order to fix this, you need to add a basename in the <Router> tag which forces the page to load at /project-name/#.
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { HashRouter as Router } from 'react-router-dom';
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Router basename={process.env.PUBLIC_URL}>
<App /> {/* The various pages will be displayed by the `Main` component. */}
</Router>
</React.StrictMode>
);
Relevant Links for more info
https://maximorlov.com/deploying-to-github-pages-dont-forget-to-fix-your-links/
https://create-react-app.dev/docs/deployment/#building-for-relative-paths

Reducer is getting called thrice for each routing without performing any action

I am trying to integrate redux with react-routing. I found a situation like,
i am accessing the same reducer by two component. i am updating the sate from one component, state is getting updated in store. while routing to the another component,again reducer is getting called automatically and intialized the state with default value.
Here what is happening as per my understanding,reducer is getting called from store and passing the state value as null, so it is taking the default value (feature of ES6) and in same way action.type would null only.
So, My question is why reducer is getting called for every routing even though there is no any user actioned performed. even though if it is calling the reducer, why store is passing null value to the state argument of reducer instead of the state updated by component before routing.
Reducer:
export const userReducer=function(state={name:"rohit",id:123},action){
console.log("user reducer called",state);
switch(action.type){
case "NEW_USER_REG":
console.log("user added");
state=Object.assign({},action.payload);
break;
case "DELETE_USER":
consol.log("user deleted");
break;
}
return state;
}
Component 1(reading and writing from store state):
import React from 'react';
import {Navbar} from '../component/navbar';
import {connect} from 'react-redux'
class Main extends React.Component{
render(){
return(
<div>
<h1>This is main comp.. below is state got from store</h1>
<input type="text" ref="name"/>
<button onClick={()=>this.props.register("rajesh")}>update state</button>
<hr></hr>
{this.props.user.name}
</div>);
}
}
const stateToprops=(state)=>{
return {
user:state.userReducer
}
}
const dispatchToProps=(dispatch)=>{
return{
register:(name)=>{
console.log("fun called ",name);
dispatch({
type:"NEW_USER_REG",
payload:{name:name,id:1}
})
}
}
}
export default connect(stateToprops,dispatchToProps)(Main);
Component 2(reading from store state):
import React from 'react';
import {connect} from 'react-redux';
export class Second extends React.Component{
render(){
return(
<div>
<h1>Hello, This is active component...</h1>
<hr></hr>
{this.props.user.name}
</div>
)
}
}
const stateToProps=(state)=>{
return{
user:state.userReducer
}
}
const dispatchToProps=(dispatch)=>{
return{
adduser:(expense)=>{
dispatch({type:"NEW_USER_REG",payload:expense})
}
}
}
export default connect(stateToProps,dispatchToProps)(Second);
Router Component :
import React from 'react';
import {
BrowserRouter as Router,
Route, Switch
} from 'react-router-dom';
import {Navbar} from '../component/navbar';
import Second from '../component/second';
import Main from '../component/main';
export class App extends React.Component{
render(){
return(
<div>
<div style={{height:80,backgroundColor:'#e8e3e4'}}></div>
<Navbar/>
<div className="text-align: center; margin: auto; width: 60%; padding: 10px;">
<div style={{height:5}}></div>
<div className="container-fluid">
<div className="row">
<div className="col-md-2"> </div>
<div className="col-md-8"style={{height:'auto',backgroundColor:'#e8e3e4'}}>
<Router>
<Switch>
<Route exact path='/' component={Main} />
<Route path='/contact' component={Second}/>
</Switch>
</Router>
</div>
<div className="col-md-2"></div>
</div>
</div>
</div>
</div>
);
}
}
anchor component using not
import React from 'react';
import {Second} from '../component/second';
export class Navbar extends React.Component{
render(){
let styles={width:10};
return(
<div >
<nav className="navbar navbar-inverse" >
<div className="container-fluid">
<div className="navbar-header">
<a className="navbar-brand" href="/">My Learning Project</a>
</div>
<ul className="nav navbar-nav">
<li className="active">Home</li>
<li className="dropdown"><a className="dropdown-toggle" data-toggle="dropdown" href="#">Service<span className="caret"></span></a>
<ul className="dropdown-menu">
<li>Register</li>
<li>Get-Profile</li>
<li>Update</li>
</ul>
</li>
<li>Contact Us</li>
<li>About</li>
</ul>
</div>
</nav>
</div>
);
}
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router,
Route, Switch
} from 'react-router-dom';
import {App} from './app'
import {store} from './store.js'
import {Provider} from 'react-redux'
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('content')
);
Could you please post some snippets of your code like the reducer which is getting called twice and the 2nd component particularly the part where you are dispatching the action. That way we can probably help you.
Solution
OP was using anchor tags <a> to navigate to different urls which were making the page to reload and the redux store to get created again. Switching to <Link> solved the issue.

Reactjs error when importing react-bootstrap

I have Login.js and this is the code:
import React, {Component} from 'react';
import {FormGroup, FormControl} from 'react-bootstrap';
class Login extends Component {
render() {
return (
<div className="middle-box text-center loginscreen animated fadeInDown">
<div>
<h1 className="logo-name">Pz</h1>
</div>
<form>
<FormGroup bsSize="large">
<FormControl type="text" placeholder="Large text" />
</FormGroup>
</form>
</div>
)
}
}
export default Login
This is my routes.js
import React from 'react'
import Main from '../components/layouts/Main';
import Blank from '../components/layouts/Blank';
import LoginView from '../views/Login';
import MainView from '../views/Main';
import MinorView from '../views/Minor';
import { Route, Router, IndexRedirect, browserHistory} from 'react-router';
export default (
<Router history={browserHistory}>
<Route path="/" component={Main}>
<IndexRedirect to="/main" />
<Route path="main" component={MainView}> </Route>
<Route path="minor" component={MinorView}> </Route>
<Route path="login" component={LoginView}> </Route>
</Route>
</Router>
);
The error is :
warning.js:45 Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components). Check the render method of Login.
invariant.js:39 Uncaught Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. Check the render method of Login.
Whats wrong with the code? please help
Yeaaaahh, i know what the problem, need the latest version of react-bootstrap.
in my case, i've used v0.30.5

React changing route breaks height with layout

I have a React application where if I change the route to a page with a small height the entire body doesn't have a max height for the window (the html does have full height).
I have a standard index.html setup here
<html>
<body>
<div id="app"></div>
<script src="client.min.js"></script>
</body>
</html>
Then here's my App.js file:
import React from "react"
import ReactDOM from "react-dom"
import {Router, hashHistory} from "react-router"
import routes from "./Routes"
const app = document.getElementById('app')
ReactDOM.render((
<Router history={hashHistory} routes={routes()}>
</Router>
), app)
And here's my Routes.js file:
import React from "react"
import {Route, IndexRoute} from "react-router"
import Layout from "./Layout"
import About from "./pages/About"
import Home from "./pages/Home"
import NotFound from "./pages/NotFound"
import Register from "./pages/Register"
import SignIn from "./pages/SignIn"
import Terms from "./pages/Terms"
export default() => {
return (
<Route name="root" path="/" component={Layout}>
<IndexRoute component={Home}/>
<Route path="/about" component={About}/>
<Route path="/signin" component={SignIn}/>
<Route path="/register" component={Register}/>
<Route path="/terms" component={Terms}/>
<Route path="*" component={NotFound}/>
</Route>
)
}
Finally here's my Layout.js:
import React from "react"
import ReactDOM from "react"
import DevTool from 'mobx-react-devtools'
import Control from "./components/layout/Control"
import Footer from "./components/layout/Footer"
import Header from "./components/layout/Header"
import Sidebar from "./components/layout/Sidebar"
export default class Layout extends React.Component {
render() {
const { location } = this.props
return (
<div className="wrapper">
<DevTool /> {/* Remove for PRODUCTION */}
<Header />
<Sidebar />
{this.props.children}
<Footer />
<Control />
<div className="control-sidebar-bg"></div>
</div>
)
}
}
All my routes go to pages with very little content so it doesn't cover the full page. In every case the entire body height wraps to the height of the content while the html remains 100% of with window.
I've tried debugging on everything. There's no padding or margin on the body or html rendered by inspecting the elements. I've also tried adding height and min-height 100% attributes to the body tags with inline styling and still didn't get any decent results.
The page automatically fixes itself as soon as the window resizes or I reload the page but that eliminates a lot of the reason to why I am using React.
Any ideas on what could fix this?
I managed to get a fix, this is quite a specific problem (which I've gather from the lack of response). But in-case anyone else stumbled across a problem like this.
All of my pages components had the following render:
export default class About extends React.Component {
render() {
return (
<div className="content-wrapper">
{/* All my about code goes in here */}
</div>
)
}
}
I ended up removing the content-wrapper classNames from all the page container dividers and did the following to the Layout page:
export default class Layout extends React.Component {
render() {
const { location } = this.props
return (
<div className="wrapper">
<DevTool /> {/* Remove for PRODUCTION */}
<Header />
<Sidebar />
<div className="content-wrapper">
{this.props.children}
</div>
<Footer />
<Control />
<div className="control-sidebar-bg"></div>
</div>
)
}
}
This solved all my problems :)