React router v6 detecting change in location [duplicate] - reactjs

im using react router v6 and i every time i use initializing for authentication in my main file it shows this error. i cant find a solution in the internet for it. i want to render some routes only when there is a user but now it doesnt render anything.
AuthNavigator
import React, { useState, useEffect } from 'react';
import app from './firebase';
import { Router, Routes, Route } from 'react-router-dom';
import AuthStack from './stacks/AuthStack';
import AppStack from './stacks/AppStack';
import StaticStack from './stacks/StaticStack';
function AuthNavigator() {
const [initializing, setInitializing] = useState(true);
const [user, setUser] = useState(() => app.auth().currentUser);
useEffect(() => {
const unsubscribe = app.auth().onAuthStateChanged((user) => {
if (user) {
setUser(user);
} else {
setUser(null);
}
if (initializing) {
setInitializing(false);
}
});
// cleanup subscription
return unsubscribe;
}, []);
if (initializing) return 'Loading....';
return (
<Router>
<Routes>
<Route path="*" element={<StaticStack />} />
<Route path="auth/*" element={<AuthStack user={user} />} />
<Route path="app/*" element={<AppStack user={user} />} />
</Routes>
</Router>
);
}
export default AuthNavigator;
App.js
import React from 'react';
import './App.css';
import AuthNavigator from './AuthNavigator';
import { Router } from 'react-router-dom';
function App() {
return (
<Router>
<AuthNavigator />
</Router>
);
}
export default App;

I had the same issue. My issue is because of the following reason.
I had a Header component which consists of NavLink which is a router component. I placed this Header component inside the App component. My App component was like this:
function App() {
return(
<Header/>
<Router>
<Routes>
<Route path="/" element={<Homepage/>}/>
<Route path="/shop" element={<Shop/>}/>
<Route path="/signin" element={<Signin/>}/>
</Routes>
</Router>
)
}
In the above App component, I have placed Header component outside of Router. Since in the Header component I have used NavLink which is a Router component caused this error. Then I moved Header component into the Router component then it worked fine. Finally my code looked like this:
function App() {
return(
<Router>
<Header/>
<Routes>
<Route path="/" element={<Homepage/>}/>
<Route path="/shop" element={<Shop/>}/>
<Route path="/signin" element={<Signin/>}/>
</Routes>
</Router>
)
}

Already wrapped in Router?
if your component is already wrapped in a Router. Make sure you are importing useLocation from react-router-dom instead of react-router. this worked for me.

Make sure that your App component in index.js is wrapped with BrowserRouter like this
const app = (
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
);

In case you run into this problem when running a test, don't forget to wrap your import of App in Router as well. My crude example is below.
import { render, screen } from '#testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import { App } from '../App';
test('renders Box', () => {
render(
<BrowserRouter>
<App />
</BrowserRouter>
);
const boxElement = screen.getByLabelText('box-outline');
expect(boxElement).toBeInTheDocument();
});

I had the same error coming up from inside a test. The component I was testing contained a NavLink component, and I wasn't rendering a Router in the test.
This error disappeared after wrapping my component in question with BrowserRouter.

I had this problem when using {useLocation} from 'react-router-dom'
function App() {
const { pathname, hash, key } = useLocation();
//function using pathname hash and key
return(
<Router>
<Header/>
<Routes>
<Route path="/" element={<Homepage/>}/>
<Route path="/shop" element={<Shop/>}/>
<Route path="/signin" element={<Signin/>}/>
</Routes>
</Router>
)
}
throws the same error even with the in the correct place
I fixed it by explicitly wrapping the useLocation() within the router
function App() {
return(
<Router>
<Header/>
<Inner/>
</Router>
)
}
function Inner() {
const { pathname, hash, key } = useLocation();
//function using pathname hash and key
return(
<Routes>
<Route path="/" element={<Homepage/>}/>
<Route path="/shop" element={<Shop/>}/>
<Route path="/signin" element={<Signin/>}/>
</Routes>
)
}

I had this error because Vite was bundling two copies of the same version of react-router-dom... check the outputted bundle for * React Router DOM and see how many copies there are.
If that's the case, the solution will differ. In my scenario I think it's because I was referencing other local npm packages using file:... once I switched to a npm workspace that fixed it.

So i fixed like this structure
index.js
import { BrowserRouter } from 'react-router-dom'
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
App.js
import { Route, Routes, Navigate } from 'react-router-dom'
<Layout>
<Routes>
<Route path="/" element={<Navigate to="/home" />} />
<Route path="/home" element={<Home />} />
{...}
<Route path="*" element={<NotFound />} />
</Routes>
</Layout>
Layout.js
<Fragment>
<Header></Header>
<main className="container">{props.children}</main>
</Fragment>
Header.js
import { Link, NavLink } from 'react-router-dom'
<header className={classes.header}>
<nav>
<NavLink
className={(navData) => (navData.isActive ? classes.active : '')}
to="/search"
>
Search
</NavLink>
</nav>
</header>
App.test.js
import { BrowserRouter } from 'react-router-dom';
it('renders learn react link', async () => {
render(<BrowserRouter><App /></BrowserRouter>)
const linkElement = await screen.findByText(/home/i)
expect(linkElement).toBeInTheDocument()
})

in my case, I faced this error when I used the HOC and context provider and placed my Routing component as the context.provider's child, and export my Provider component by HOC like this:
class Provider extends Component {
render() {
return (
<Context.Provider
value={{
something: this.state.something
}}
>
<Routing />
</Context.Provider>
);
}
}
export default HOC(Provider)

im my case, the problem was putting BrowserRouter inside App.js file, solved it by moving this into index.js file and wrapping it around App.js
Former Index.js
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<React.StrictMode>
<PersistGate persistor={persistor} >
<App/>
</PersistGate>
</React.StrictMode>
</Provider>
);
reportWebVitals();
Former App.js
import { BrowserRouter, Routes, Route, useLocation} from "react-router-dom";
const App = () => {
const {pathname} = useLocation()
return (
<div className='app'>
<BrowserRouter>
<Routes>
<Route path='/*' element={<LandingPage />} />
</Routes>
</BrowserRouter>
</div>
);
};
export default App;
New Index.js
import { BrowserRouter } from 'react-router-dom';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<React.StrictMode>
<PersistGate persistor={persistor} >
<BrowserRouter >
<App/>
</BrowserRouter>
</PersistGate>
</React.StrictMode>
</Provider>
);
reportWebVitals();
New App.js
import { Routes, Route, useLocation} from "react-router-dom";
const App = () => {
const {pathname} = useLocation()
return (
<div className='app'>
<Routes>
<Route path='/*' element={<LandingPage />} />
<Route path='/registeration' element={<Registration />} />
</Routes>
</div>
);
};
export default App;

Try this:
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

Related

how to solve Matched leaf route at location "/project" does not have an element error?

I'm learning react routing but when I try to use BrowserRouter I'm getting the following error:
Matched leaf route at location "/project" does not have an element.
This means it will render an <Outlet /> with a null value by default
resulting in an "empty" page.
in Routes (created by Profile)
in Profile (created by App)
in App
PFA the code below.
index.js
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
root.render(
<StrictMode>
<App />
</StrictMode>
);
APP.JS
import "./styles.css";
import Profile from "./Profile";
import { BrowserRouter } from "react-router-dom";
export default function App() {
return (
<div className="App">
<BrowserRouter>
<Profile />
</BrowserRouter>
</div>
);
}
PROFILE.JS
import Home from "./Home";
import Projects from "./Projects";
import Blogs from "./Blogs";
import { Route, Routes, Switch } from "react-router-dom";
import { BrowserRouter, Link } from "react-router-dom";
const Profile = () => (
<div>
<Routes>
<Route exact path="/" component={Home} />
<Route path="/project" component={Projects} />
<Route path="/blog" component={Blogs} />
</Routes>
</div>
);
export default Profile;
HOME.JS
const Home = () => {
return <div>Hi im Home page</div>;
};
export default Home;
Please note project.js and blog.js is similar to home.js
You appear to be using react-router-dom#6. The Route component API changed significantly from v5. A single element prop replaced the component and render and children function props that takes a ReactNode, a.k.a. JSX, value.
Replace the component prop with the element prop and render the routed components as JSX.
const Profile = () => (
<div>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/project" element={<Projects />} />
<Route path="/blog" element={<Blogs />} />
</Routes>
</div>
);
See the Upgrading from v5 migration guide for other breaking changes between v5 and v6.

One router work but other router not work

Hey i have a reactjs app with this as app.tsx
import tw from 'twin.macro';
import { hot } from 'react-hot-loader/root';
import { Route, BrowserRouter as Router, Routes as Switch } from 'react-router-dom';
import Main from './Main';
import Test from './Test';
const App = () => {
return (
<><Main /><div css={tw`mx-auto w-auto`}>
<Router>
<Switch>
<Route path="/element" element={<Test />} />
<Route path="/" element={<Main />} />
</Switch>
</Router>
</div></>
);
};
export default hot(App);
But when i run a ./node_modules/.bin/webpack --watch --progress the localhost/ work but localhost/element not work i have a 404 error
Not Found The requested URL was not found on this server
Can you tell me why its not work?
(i use 6.2.1 of react-router-dom)
first and foremost you need to mention the version you are using , and try this if it works for u :-
your components should look like this, to work:-
import tw from 'twin.macro';
import { hot } from 'react-hot-loader/root';
import { Route, Routes} from 'react-router-dom';
import Main from './Main';
import Test from './Test';
const App = () => {
return (
<><Main /><div css={tw`mx-auto w-auto`}>
<Routes>
<Route exact path="/element" element= {<Test />} />
<Route exact path="/" element= {<Main/>} />
</Routes>
</div></>
);
};
NB: try to wrap your index.tsx component with the <BrowserRouter> </BrowserRouter> like this :
import { BrowserRouter } from "react-router-dom";
ReactDOM.render( <BrowserRouter> <App/> </BrowserRouter>, document.getElementById('root'))
therefore you can remove the BrowserRouter from the app.tsx
I think you're using ‘react-router-dom’ newer version. Switch is no longer in the new version. please read here
Switch' is not exported from 'react-router-dom'
import { Route, BrowserRouter as Router, Routes as Switch } from 'react-router-dom';
function App() {
const Main = () => {
return (
<h1>Main</h1>
)
}
const Test = <h1>Test</h1>
return (
<div >
<Router>
<Switch>
<Route path="/element" element={<Main />} />
<Route path="/" element={Test} />
</Switch>
</Router>
</div>
);
}
export default App;
You need to use the <Main /> structure

React router error "TypeError: Object(...) is not a function"

im currently learning react. During course about routing i get this error Screenshoot I' ve been making sure that i' ve write code right and trying my best to find solution for around 3 hours now and i cant solve this for my own so i am seeking for help.
import React from "react";
import "./index.css";
import { BrowserRouter, Route } from 'react-router-dom';
import TwittersView from '../TwittersView/TwittersView';
import ArticlesView from '../ArticlesView/ArticlesView';
import NotesView from '../NotesView/NotesView';
render() {
return (
<BrowserRouter>
<>
<h1>hello world</h1>
<Route exact path="/" component={TwittersView} />
<Route path="/articles" component={ArticlesView} />
<Route path="/notes" component={NotesView} />
</>
</BrowserRouter>
);
}
}
export default Root;
You need to wrap your <Route> component with <Routes> component.
And react-router-dom v5 and v6 has different syntax to render routes.
Here is the example with react-router-dom v6.
import React from "react";
import { BrowserRouter, Link, Route, Routes } from "react-router-dom";
const TwittersView = () => {
return <h1>Twitter view</h1>;
};
const ArticlesView = () => {
return <h1>Articles view</h1>;
};
const NotesView = () => {
return <h1>Notes view</h1>;
};
const App = () => {
return (
<BrowserRouter>
<Link to="/">TwittersView</Link>
<Link to="/articles">ArticlesView</Link>
<Link to="/notes">NotesView</Link>
<Routes>
<Route path="/" element={<TwittersView />} />
<Route path="/articles" element={<ArticlesView />} />
<Route path="/notes" element={<NotesView />} />
</Routes>
</BrowserRouter>
);
};
export default App;
the component is no longer in accord with the latest versions of react also I think Switch is not working now Routes has been replaced don't know why this doesn't reflect latest documentation.
import { BrowserRouter, Route, Routes } from 'react-router-dom';
.
.
.
<BrowserRouter>
//Navlink handeling here ie Navbar component with custom css
<Routes>
<Route path='/' element={<ElementName />}/>
<Route path='/aboutus' element={<ElementName />}/>
</Routes>
</BrowserRouter>

react redirect not working when some routes are inside a custom component

Live preview
I have a simple routing stragary.
for /login -> show LoginPageContainer
for /register -> show LoginPageContainer again
for / -> redirect to /login
for * -> show NotFoundPage
If all routes are at same level everything works fine.
<BrowserRouter>
<Switch>
{/*<App />*/}
<Route path={'/login'} component={LoginPageContainer}/>
<Route path={'/register'} component={LoginPageContainer}/>
<Route exact path="/">
<Redirect to="/login" />
</Route>
<Route path='*' component={NotFoundPage} />
</Switch>
</BrowserRouter>
But If login and register routes are inside App component, / and * routes show nothing.
Index.js
<Switch>
<App />
{/*<Route path={'/login'} component={LoginPageContainer}/>*/}
{/*<Route path={'/register'} component={LoginPageContainer}/>*/}
<Route exact path="/">
<Redirect to="/login" />
</Route>
<Route path='*' component={NotFoundPage} />
</Switch>
App.js
render() {
const { alert } = this.props;
return (
<div className="container">
<div className="col-sm-8 col-sm-offset-2">
<Route path={'/login'} component={LoginPageContainer}/>
<Route path={'/register'} component={LoginPageContainer}/>
</div>
</div>
);
}
Full code
index.js
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { store } from './helpers';
import { App } from './App';
import { configureFakeAPI } from './helpers';
import {BrowserRouter, Switch} from "react-router-dom";
import { Router, Route, Redirect } from 'react-router-dom';
import {NotFoundPage} from "./components/NotFoundPage";
import LoginPageContainer from "./components/LoginPage";
configureFakeAPI();
render(
<Provider store={store}>
<BrowserRouter>
<Switch>
<App />
{/*<Route path={'/login'} component={LoginPageContainer}/>*/}
{/*<Route path={'/register'} component={LoginPageContainer}/>*/}
<Route exact path="/">
<Redirect to="/login" />
</Route>
<Route path='*' component={NotFoundPage} />
</Switch>
</BrowserRouter>
</Provider>,
document.getElementById('app')
);
App.js
import React from 'react';
import {Router, Route, Switch} from 'react-router-dom';
import { connect } from 'react-redux';
import { PrivateRoute } from './PrivateRoute.js';
import { history } from './helpers';
import { alertActions } from './actions';
import { HomePage } from './components/HomePage';
import LoginPageContainer from './components/LoginPage';
import { RegisterPage } from './components/RegisterPage';
import './styles.css';
export class App extends React.Component {
constructor(props) {
super(props);
const { dispatch } = this.props;
history.listen((location, action) => {
});
}
render() {
const { alert } = this.props;
return (
<div className="container">
<div className="col-sm-8 col-sm-offset-2">
<Route path={'/login'} component={LoginPageContainer}/>
<Route path={'/register'} component={LoginPageContainer}/>
</div>
</div>
);
}
}
function mapStateToProps(state) {
const { alert } = state;
return {
alert
};
}
export default connect(mapStateToProps)(App);
The routes you mentioned show nothing, I believe, because <Switch/> only expects <Route/> inside of it, and is looking to match the current location to those routes. But you're feeding it <App/> which makes it always return that and stop.
You either need to put <App/> itself in a <Route/> inside of the switch or take it outside, and maybe use another <Switch/> for the nested routes in the component.

React-Router & MobX - Provider

I am trying to access my store from every component page I have, so I followed the following tutorial in order to connect React Router & MobX.
http://frontendinsights.com/connect-mobx-react-router/
However, I am facing a problem at The MobX way – Provider component.
This is the code exmaple:
import { Provider } from 'mobx-react';
import usersStore from './stores/usersStore';
import itemsStore from './stores/itemsStore';
const stores = { usersStore, itemsStore };
ReactDOM.render(
<Provider {...stores}>
<Router history={history}>
<Route path="/" component={App}>
</Route>
</Router>
</Provider>,
document.getElementById('app')
);
I tried to do the same in index.js
import React from 'react'
import { render } from 'react-dom'
import { Router, hashHistory, Route, IndexRedirect } from 'react-router'
import App from './webapp/App'
import Home from './components/pages/Home'
import Dogs from './components/pages/Dogs'
import Cats from './components/pages/Cats'
import Provider from 'mobx-react'
import RootStore from './webapp/stores'
const store = RootStore
render((
<Provider rootStore={store}>
<Router history={hashHistory}>
<Route path="/" component={App}>
<IndexRedirect to="/home" />
<Route path="/home" component={Home}/>
<Route path="/dogs" component={Dogs}/>
<Route path="/cats" component={Cats}/>
</Route>
</Router>
</Provider>
), document.getElementById('app'))
However, because of <Provider/>, I am getting an error:
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).
Why am I getting that? It should work doesn't it?
Thanks for any help !
If it's a web app, react-router-dom should be used.
Here is the correct way to inject store with Provider https://github.com/mobxjs/mobx-react#observer
I wrote a solution for your code without using decorator, so it supports create-react-app:
import React, { Component } from 'react';
import { Provider, Observer } from 'mobx-react';
import { observable } from 'mobx';
import { BrowserRouter, Switch, Route, Link, Redirect } from 'react-router-dom';
const myStore = observable({
home: 'Home',
cat: 'Cat',
});
const Home = () => (
<Observer
inject={stores => ({ myStore : stores.myStore })}
render={props => (<section><h1>{props.myStore.home}</h1></section>)}
/>
);
const Cat = () => (
<Observer
inject={stores => ({ myStore : stores.myStore })}
render={props => (<section><h1>{props.myStore.cat}</h1></section>)}
/>
);
class App extends Component {
render() {
return (
<BrowserRouter>
<Provider myStore={myStore}>
<div className="App">
<header className="App-header">
<nav>
<ul>
<li><Link to="/home">HOME</Link></li>
<li><Link to="/cat">CAT</Link></li>
</ul>
</nav>
</header>
<Switch>
<Route path='/home' exact component={Home} />
<Route path='/cat' exact component={Cat} />
<Redirect from="/" to="/home" />
</Switch>
</div>
</Provider>
</BrowserRouter>
);
}
}
export default App;
All the components are in App.js file. There is no change in default index.js from create-react-app.
Note:
The another way to doing this, it's to simply create a singleton class for the store and use export default new Store() to make it available to all components. The class itself doesn't have to be observable, but its properties do.

Resources