I'm using the react-router-dom Link component to manage my navigation but it doesn't work.
The Link changes the URL but doesn't render the component.
Here is a simple app describing my problem. I'm trying to use My App header as go home link:
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import React from 'react';
const Navigation = () => {
return (
<div>
<Link to="/events">
<h1>My Application</h1>
</Link>
</div>
);
};
const ConnectedNavigation = connect((state) => state)(Navigation);
export default ConnectedNavigation;
App.jsx code :
import React from 'react';
import { Provider } from 'react-redux';
import { store } from '../store/index';
import ConnectedDashboard from './Dashboard';
import ConnectedEventDetails from './EventDetails';
import { Router, Route } from 'react-router-dom';
import { history } from '../store/history';
import ConnectedNavigation from './Navigation';
export const Main = () => (
<Router history={history}>
<Provider store={store}>
<div>
<ConnectedNavigation />
<Route exact path="/events" render={() => <ConnectedDashboard />} />
<Route
exact
path="/event/:id"
//match prop is necessary in order to determine which event
//we are looking for
render={({ match }) => <ConnectedEventDetails match={match} />}
/>
</div>
</Provider>
</Router>
);
As you can see i added exact on my Routes to avoid any confusions
This problem comes from this line:
import { Router, Route } from 'react-router-dom';
The correct import is :
import { BrowserRouter as Router, Route } from 'react-router-dom';
Related
I have been trying to integrate Google analytics in my react app and i used every way mentioned on this thread and all solutions are failing. Below are the methods i tried and the corresponding error i am getting. Hope someone can help
import React, { Fragment } from 'react';
import store from './Store';
import { Router, Route, Switch } from 'react-router-dom';
import { Provider } from 'react-redux';
import Navbar from './components/layout/Navbar';
import Login from './components/auth/Login';
import Footer from './components/layout/Footer';
import MobileMenu from './components/layout/MobileMenu';
import Tutorial from './components/layout/Tutorial';
import ReactGA from 'react-ga';
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
ReactGA.initialize('G-11111111');
history.listen((location, action) => {
ReactGA.pageview(location.pathname + location.search);
console.log(location.pathname);
});
const App = () => {
return (
<div className="App">
<Provider store={store}>
<MuiThemeProvider theme={theme}>
<Router history={history}>
<Fragment>
<Navbar />
<Switch>
<Route exact path="/" component={Login} />
<Route exact path="/tutorial" component={Tutorial} />
</Switch>
<MobileMenu />
<Footer />
</Fragment>
</Router>
</MuiThemeProvider>
</Provider>
</div>
);
};
export default App;
The first page loads normally but if i click on any link from my Switch i get a blank page and the following warning
react_devtools_backend.js:2450 [react-ga] path is required in .pageview()
Second method i tried with hooks i get same error
import React, { Fragment, useEffect } from 'react';
import store from './Store';
import { Router, Route, Switch } from 'react-router-dom';
import { Provider } from 'react-redux';
import Navbar from './components/layout/Navbar';
import Login from './components/auth/Login';
import Footer from './components/layout/Footer';
import MobileMenu from './components/layout/MobileMenu';
import Tutorial from './components/layout/Tutorial';
import ReactGA from 'react-ga';
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
ReactGA.initialize('G-11111111');
history.listen((location, action) => {
ReactGA.pageview(location.pathname + location.search);
});
const App = () => {
useEffect(() => {
ReactGA.pageview(window.location.pathname + window.location.search);
}, []);
return (
<div className="App">
<Provider store={store}>
<MuiThemeProvider theme={theme}>
<Router history={history}>
<Fragment>
<Navbar />
<Switch>
<Route exact path="/" component={Login} />
<Route exact path="/tutorial" component={Tutorial} />
</Switch>
<MobileMenu />
<Footer />
</Fragment>
</Router>
</MuiThemeProvider>
</Provider>
</div>
);
};
export default App;
Third way i tried using useLocation() and no history
import React, { Fragment, useEffect } from 'react';
import store from './Store';
import {
BrowserRouter as Router,
Route,
Switch,
useLocation
} from 'react-router-dom';
import { Provider } from 'react-redux';
import Navbar from './components/layout/Navbar';
import Login from './components/auth/Login';
import Footer from './components/layout/Footer';
import MobileMenu from './components/layout/MobileMenu';
import Tutorial from './components/layout/Tutorial';
import ReactGA from 'react-ga';
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
ReactGA.initialize('G-11111111');
const App = () => {
const location = useLocation();
// Fired on every route change
useEffect(() => {
ReactGA.pageview(location.pathname + location.search);
}, [location]);
return (
<div className="App">
<Provider store={store}>
<MuiThemeProvider theme={theme}>
<Router history={history}>
<Fragment>
<Navbar />
<Switch>
<Route exact path="/" component={Login} />
<Route exact path="/tutorial" component={Tutorial} />
</Switch>
<MobileMenu />
<Footer />
</Fragment>
</Router>
</MuiThemeProvider>
</Provider>
</div>
);
};
export default App;
I get the following error
TypeError: Cannot read property 'location' of undefined
Most likely it depends on whether you are using a Google Analytics 4 Property ID (G-XXXXXXXX), while the React Analytics package in question works for Universal Analytics. I suggest you create a Universal Analytics Property (as shown in following image) and use the relative identifier UA-XXXXXXX-X:
I have to combine use of Redux and React Router.
I tried react Router alone first and when I was clicking my images I was correctly redirected.
I followed redux tutorial and now when I click my images, I change the address (ex: http://localhost:3000/contact) but nothing displays as if the component was empty.
Root.js
import React from 'react';
import './index.css';
import PropTypes from 'prop-types'
import ReactDOM, { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom'
import App from './App'
import Users from './users'
import Book from './Book'
import Notfound from './notfound'
import { Provider } from 'react-redux';
import Store from './redux/Store/store'
import * as serviceWorker from './serviceWorker';
const Root = ({ store }) => (
<Provider store = { Store }>
<Router>
<div>
<Switch>
<Route exact path="/:filter?" component={App} />
<Route path="/users" component={Users} />
<Route path="/book" component={Book} />
<Route path='/manual' component={() => { window.location = 'https://------'; return null;} }/>
<Route path='/contact' component={() => { window.location = 'https://-------'; return null;} }/>
<Route component={Notfound} />
</Switch>
</div>
</Router>
</Provider>
)
Root.propTypes = {
store: PropTypes.object.isRequired
}
serviceWorker.unregister();
export default Root
index.js:
import React from 'react'
import { render } from 'react-dom'
import { createStore } from 'redux'
import myReducer from './redux/Reducers/myReducer'
import Root from './Root'
const store = createStore(myReducer)
render(<Root store={store} />, document.getElementById('root'))
App.js:
import React from 'react'
import { Route, Link, Redirect, withRouter, BrowserRouter as Router } from 'react-router-dom'
import logo from './images/logo.png';
import book from './images/book.png';
class App extends React.Component {
constructor() {
super();
this.state = {
date: new Date()
};
}
render() {
const { date } = this.state;
return (
<div>
<img src={logo} />
<img src={book} onClick={() => this.props.history.push('/book')}/>
<img src={call} onClick={() => this.props.history.push('/contact')}/>
</div>
)
}
}
export default App
Do you know what is wrong ?
A few things I noticed:
When using react router you shouldn't use window.location to redirect since this reloads the whole page. The <Redirect> component from react-router is a better choice here.
Also you shouldn't use the component prop on the <Route>-component for things that aren't actually components, as there's the render prop for that (more on that here).
Furthermore: <Route exact path="/:filter?" component={App} /> is not going to work since :filter? is looking for a variable and exact is looking for an exact match. Moreover you probably shouldn't put the flexible one first since it's going to match every route that you throw at it. So all the following routes are practically unreachable.
today i'm trying to implement Redux for the first time on a react-app because it has been a mess to manage state/props, it's pretty good on the redux side so far but when i try to link my store with my app + router i run into errors.
Depending on how i place my router tags 2 things appens:
-not compiling (most of the time because i have outside of the router)
-compiling, rendering but when i try to navigate url changes but not the components that should render.
I did many tries (a lot) so i reverted to when i just linked the store.
Below is my index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import 'bootstrap/dist/css/bootstrap.css';
import { BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux'
import store from './store'
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>,
document.getElementById('root')
);
And my App.js (shorthen because it's long and messy):
import React, { Component } from 'react';
import { Route, Switch, Link } from 'react-router-dom';
import { connect } from 'react-redux'
// Components imports
import { Provider } from 'react-redux'
import store from './store'
import { ensureAuth, login, register, updateInputAuth, logout } from './actions/authActions'
class App extends Component {
//states
//methods
render() {
const { pathname } = window.location
const { logged, user, loginError, registerError, inputLogin, inputRegister, successMessage } = this.props
return (
<>
<nav className="navbar navbar-expand-lg navbar-light bg-light" id="navbar">
// My app navbar basically, usses <Link> tags
</nav>
{
!logged ?
<>
<ModalConnect />
<ModalRegister />
</>
: null
}
<>
<Switch>
<Route exact path='/' component={Root}/>
<Route path='/ground' render={(props) => <GroundAnalizer {...props} logged={this.state.logged} />} />
<Route path='/air' component={AirAnalizer} />
<Route path='/simulateur' render={(props) => <Simulateur {...props} logged={logged} log={this.connect} reg={this.register} onInputChange={this.onInputChange} register={this.state.register} login= {this.state.login} errors={this.state.errors} errorsLog={this.state.errorsLog} confirmMsg={this.state.confirmMsg} />} />
<Route path='/calculateur-route' component={CalculateurRoute} />
<Route path='/triangulateur' component={Triangulateur} />
</Switch>
</>
</>
)
}
}
export default connect((store) => {
return{
logged: store.auth.logged,
user: store.auth.user,
loginError: store.auth.loginError,
registerError: store.auth.registerError,
inputLogin: store.auth.inputLogin,
inputRegister: store.auth.inputRegister,
successMessage: store.auth.successMessage,
}
})(App)
So there it is, what am i doing wrong and how i should add my store/routing so it does work ?
Take a look at this document.
You need to import withRouter from react-router-dom and wrap the connect export you have there with a call to withRouter in the components that use React Router navigation.
Thus, your code should be something like:
// Before
export default connect((store) => {
return{
logged: store.auth.logged,
user: store.auth.user,
loginError: store.auth.loginError,
registerError: store.auth.registerError,
inputLogin: store.auth.inputLogin,
inputRegister: store.auth.inputRegister,
successMessage: store.auth.successMessage,
}
})(App)
// After
import { withRouter } from 'react-router-dom';
export default withRouter(connect((store) => {
return{
logged: store.auth.logged,
user: store.auth.user,
loginError: store.auth.loginError,
registerError: store.auth.registerError,
inputLogin: store.auth.inputLogin,
inputRegister: store.auth.inputRegister,
successMessage: store.auth.successMessage,
}
})(App))
This link also has some more information on how this works.
Hi I am new in react and I want to implement routing with Loadable, But Its not working Its showing blank page when either http://localhost:3000/user or http://localhost:3000/
Could you please correct me where I am doing wrong.
I am also getting-
Warning: Failed prop type: Invalid prop component of type string supplied to Route, expected function.
My codes are:
home.js
import React, { Component } from 'react';
import { Link} from 'react-router-dom';
class Home extends Component {
render() {
return (
<div>
<h1>Welcome to the Tornadoes Website!</h1>
<h5><Link to="/user">User</Link></h5>
</div>
);
}
}
export default Home;
user.js:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
class User extends Component {
render() {
return (
<div>
<ul>
<li>6/5 # Evergreens</li>
<li>6/8 vs Kickers</li>
<li>6/14 # United</li>
<li><Link to="/">Home</Link></li>
</ul>
</div>
)
}
}
export default User;
App.js:
import React from 'react';
import { Router, Route, Switch } from 'react-router-dom';
import { history } from './helpers/history';
import Loadable from 'react-loadable';
import './App.css';
const Loading = () => <div> Loading... </div>;
const Home = Loadable({
loader: () => import('./components/home-component/home'),
loading: Loading
});
const User = Loadable({
loader: () => import('./components/user-component/user'),
loading: Loading
});
class App extends React.Component {
render() {
return (
<Router history={history}>
<Switch>
<Route exact path="/" component="Home" />
<Route path="/user" component="User" />
</Switch>
</Router>
);
}
}
export default App;
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { BrowserRouter } from 'react-router-dom'
ReactDOM.render((
<BrowserRouter>
<App />
</BrowserRouter>
), document.getElementById('root'))
registerServiceWorker();
I see you are doing this: <Route exact path="/" component="Home" /> which should be <Route exact path="/" component={Home} /> since you want to use that variable, it's impossible to reference by String when he can't know which Component you want. I hope this helps
This looks to me like there is a isRequired propType that you have missed when calling your component. Can you post your components here as well?
I am currently experimenting with the use of React Router on the website I am building. I came across the use of React Router in order to navigate through my website, and also do other things like read parameter values etc. However, I find it to be slightly confusing. You see, on my administrator login page, the router only works some times - but I haven't really figured out when and when not. I am using this.props.history.push('/admin/dashboard'), which I believe is the correct way of doing it. This is currently my setup in index.js where i have all my routes:
import React from 'react';
import ReactDOM from 'react-dom';
import registerServiceWorker from './registerServiceWorker';
import './css-styling/styling.css'
import Frontpage from './Frontpage';
import { BrowserRouter, Route, Router, Switch, Link, NavLink } from 'react-router-dom';
import AdminLogin from './Admin-Login';
import AdminWelcome from './Admin-Welcome';
import Authentication from './components/Authentication';
const websiteRoutes = (
<Router history={history}>
<div>
<Switch>
<Route path="/" component={Frontpage} exact={true}/>
<Route path="/admin" component={AdminLogin} exact={true}/>
<Authentication props={this.props}>
<Route path="/admin/welcome" component={AdminWelcome} exact={true}/>
</Authentication>
</Switch>
</div>
</Router>
);
var appRoot = document.getElementById('root');
registerServiceWorker();
ReactDOM.render(websiteRoutes, appRoot);
And each 'component' has its structure like this:
import React from 'react';
import ReactDOM from 'react-dom';
import AdminHeader from './components/Admin-Header';
import AdminPanelLogin from './components/Admin-Panel-Add-News';
import history from './components/History';
class AdminLogin extends React.Component{
render() {
return(
<div>
<AdminHeader />
<AdminPanelLogin />
</div>
);
}
}
export default AdminLogin;
What seem to be the problem here? I have tried a lot of different solutions, without having any luck. One of them was creating this 'global history', which you can see that I have imported in my AdminAddNews class.
What is the correct way of using React Router in my case?
By the way; The history.push happens inside my AdminPanelLogin component, where the code looks like this:
import React from 'react';
import ReactDOM from 'react-dom';
import { Icon, Input, Button, Message } from 'semantic-ui-react';
import {auth} from './Firebase';
import {NotificationContainer, NotificationManager} from 'react-notifications';
import { withRouter, Redirect } from 'react-router-dom';
import history from './components/History';
class AdminLogin extends React.Component{
constructor(props){
super(props);
this.handleLogin = this.handleLogin.bind(this);
this.clickLogin = this.clickLogin.bind(this);
this.performLogin = this.performLogin.bind(this);
}
handleLogin(e){
this.setState({
[e.target.name]: e.target.value
});
}
clickLogin(e){
e.preventDefault();
auth.signInWithEmailAndPassword(this.state.email, this.state.password).then(() => {
this.props.history.push('/admin/dashboard');
}).catch((error)=> {
})
}
render() {
return (
<HTMLGOESHERE>
);
}
}
export default AdminLogin;
Few things, that you need to correct,
First: In your Routes you have passed history but you have not created a custom history anywhere. You can simply use BrowserRouter for now.
Second: Write your authentication component as Wrapper to your Routes instead of using your Routes as children to it
Authentication:
const PrivateRoute = (props) => {
const userKey = Object.keys(window.localStorage)
.filter(it => it.startsWith('firebase:authUser'))[0];
const user = userKey ? JSON.parse(localStorage.getItem(userKey)) : undefined;
if (user) {
return <Route {...props} />
} else {
return <Redirect to='/admin'/>
}
}
export default PrivateRoute;
Now you Routes can be
import { BrowserRouter as Router, Route, Router, Switch } from 'react-router-dom';
import Authentication from './Authentication';
const websiteRoutes = (
<Router>
<div>
<Switch>
<Route path="/" component={Frontpage} exact={true}/>
<Route path="/admin" component={AdminLogin} exact={true}/>
<Authentication path="/admin/welcome" component={AdminWelcome} exact={true}/>
</Switch>
</div>
</Router>
);
Apart from this check how to Programmatically Navigate with react-router
Actually, you have to use browserHistory, which is a function of react-router.I hope following snippet will help you,
Import react-router in your index.js
import {Router, Route, browserHistory} from 'react-router';
ReactDOM.render(
<Router history={browserHistory} >
<Route path="/admin/somethingZero" component={somethingZero} />
<Route path="/admin/somethingOne" component={somethingOne}/>
</Router> , document.getElementById("root")
)
you can navigate between the components, by using browserHistory.push function
clickLogin(){
browserHistory.push('/admin/dashboard')
}
Also, go on with this tutorial, it will give better understanding of routers.