I have little issue I face the first time. I'm trying to use a simple useState but for some reason I can't understand why React throws me back an error and whatever I'm trying to do-nothing fix it.
that's the image of the error:
error description:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
my code:(very simple)
import React, {useState} from "react";
function Login() {
const [user, setUser] = useState({});
return <div> why error? </div>;
}
export default Login;
Tried following their solution with no luck of succeeding... thanks
EDIT: this is where I render the component -
import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import Home from "./components/Home";
import Contact from "./components/Contact";
import Login from "./components/Login";
import Register from "./components/Register";
import NotFound from "./components/NotFound";
import Navbar from "./components/Navbar";
function App() {
return (
<Router>
<div className="App">
<Navbar />
<Switch>
<Route path="/" exact render={Home} />
<Route path="/contact" exact component={Contact} />
<Route path="/login" exact render={Login} />
<Route path="/register" exact render={Register} />
<Route render={NotFound} />
</Switch>
</div>
</Router>
);
}
...
The issue here is how you're rendering your component. You can't do:
Login()
but you can do:
<Login />
Update: similarly, you can't do:
<Route path="/login" exact render={Login} />
you need:
<Route path="/login" exact render={() => <Login />} />
The function itself has no errors. Tried this in another component in a different file. Check for errors elsewhere. What were the other 40 lines in the code?
And what's the version of React?
Related
I have made use of react js memory router as below in my App.js -
import logo from './logo.svg';
import './App.css';
import './Components/Login'
import Login from './Components/Login';
import {useSelector} from 'react-redux';
import { useEffect } from 'react';
import Welcome from './Components/Welcome';
import{MemoryRouter as Router, Route, Switch} from 'react-router-dom'
function App() {
const state = useSelector(state => state.allReducers)
console.log(state.user.isValid);
return (
<Router>
<Switch>
<Route exact="/" component={Login}></Route>
<Route exact="/" component={Welcome}></Route>
</Switch>
<div className="App">
{state.user.isValid==false ||state.user.isValid== undefined ? <Login></Login> : <Welcome name={state.user.userName}></Welcome>}
</div>
</Router>
);
}
export default App;
But this is displaying my Login component twice on the screen.
How can I avoid this?
Your route configs should be:
<Switch>
<Route path="/login" component={Login} />
<Route path="/" component={Welcome} exact={true} />
</Switch>
exact should be a boolean value. And it'll tell the router only render the route match exactly with the URL. It means, the router only renders the Welcome component when the user stays at /.
But after you changed to my suggestion, you still see 2 login forms if you navigate to /login. Because the div.app will be rendered for every route :D
You're using the same route for both components: <Route exact="/"... so React will show you both. Use different routes for each component. And your syntax is a bit wrong. Like this:
<Switch>
<Route exact path="/"><Welcome /></Route>
<Route exact path="/login"><Login /></Route>
</Switch>
I have the following react component which I am trying to implement in next.js.
React component:
import React from "react";
import { Route, Switch, Redirect, withRouter } from "react-router-dom";
import Dashboard from "../../pages/dashboard";
import Profile from "../../pages/profile";
function Layout(props) {
return (
<>
<Switch>
<Route
exact
path="/"
render={() => <Redirect to="/app/dashboard" />}
/>
<Route path="/app/dashboard" component={Dashboard} />
<Route path="/app/profile" component={Profile} />
</Switch>
</>
);
}
export default withRouter(Layout);
As I am very new to next. j's, I am not sure on, how can I handle the routes with redirect in next.js similar to above react component code.
Any help is appreciated?
You are using React-Router with NextJS which is possible but not the best practice.
NextJS router is a pretty complicated thing as it handles ClientSide and ServerSide routing simultaneously.
your /app/dashboard and /app/profile pages should render properly. If you want to redirect / to /app/dashboard you can use this trick inside the getInitialProps of the pages/index.js file.
I am trying to do a basic router with history, I have:
import {BrowserRouter, Route} from 'react-router-dom';
import createBrowserHistory from 'history/createBrowserHistory'
...
render() {
return (
<BrowserRouter>
<Switch>
<Route path="/login" component={PageA}/>
<Route path="/dashboard" component={PageB}/>
<Route path="/companies" component={PageC}/>
</Switch>
</BrowserRouter>
)
}
}
ReactDOM.render(<App />, document.getElementById('app'))
But I keep getting:
Uncaught Error: React.Children.only expected to receive a single React element child
The error is repeated four times in console.
I have followed a number of other answers on forums but it still doesn't work.
What is wrong with this?
To keep things clean:
You should create a history.js in the src like so:
import createHistory from 'history/createBrowserHistory';
export default createHistory();
In your index.js import Router not BrowserRouter and pass the history as a prop like so:
import {Router, Route, Switch} from 'react-router-dom';
import history from '../history' // relative path to the file you created above...
...
render() {
return (
<Router history={history}> // pass it as a prop here...
<Switch>
<Route path="/login" component={PageA}/>
<Route path="/dashboard" component={PageB}/>
<Route path="/companies" component={PageC}/>
</Switch>
</Router>
)
}
}
Now you can use history.push('/path_you_want') to redirect after an action etc...
Side-Note: This is probably overkill if you're not using redux... For simpler redirects look into the <Redirect /> component offered by the library... more info with examples: https://reacttraining.com/react-router/web/api/Redirect
I was using the following code from an online course for React routing:
import { Router, Route, browserHistory } from 'react-router';
ReactDOM.render(
<Router history={browserHistory}>
<Route path="/" component={App></Route>
<Route path="/One" component={One}></Route>
<Route path="/Two" component={Two}></Route>
</Router>, document.getElementById('root'));
It gave me a following error 'react-router' does not contain an export named 'browserHistory'.
I did some research and found that I was using React Router v4, and the above code was for v3, so i found that I should be using <BrowserRouter> instead of <Router> so I changed my code to:
import { BrowserRouter, Route, Switch } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter history={History}>
<div>
<Route path="/" component={App}></Route>
<Route path="/One" component={One}></Route>
<Route path="/Two" component={Two}></Route>
<Route path="*" component={NoMatch}></Route>
</div></BrowserRouter>, document.getElementById('root'));
History I have in a separate file:
import { createBrowserHistory } from 'history'
export default createBrowserHistory();
Now the page loads without an error but if I use Developer tools, I can see a warning:
Warning: <BrowserRouter> ignores the history prop. To use a custom history, use `import { Router }` instead of `import { BrowserRouter as Router }`."
Another issue is that <Route path="*" component="NoMatch}></Route> only supposed to load NoMatch component when no path specified in the router but it loads on every page, regardless.
Can anyone help figure out how can I fix the issues?
I am assuming you are using react-router v4
Firstly, Instead of <BrowserRouter> make use of <Router>
import { Router } from 'react-router-dom';
You can get access to the history object's properties by using <withRouter> as mentioned Here
Export the component using <withRouter> , something like :
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
class SomeComponent extends Component {
render() {}
}
export default withRouter(SomeComponent);
Secondly , you can make use of <Switch> as it renders the first child <Route> or <Redirect> that matches the location
And you can wrap a <Switch> in a <div> like this:
<Router>
<div>
<Switch>
<Route path="/" component={App}></Route>
<Route path="/One" component={One}></Route>
<Route path="/Two" component={Two}></Route>
<Route component={NoMatch}></Route>
</Switch>
</div>
</Router>
NOTE : Last Route doesn't have path="*"
You can read more about <Switch> on a ReactTraining Github
If you want to read more about React Router V4 or <withRouter> , You can read on this Medium Article
You can only use history with <Router> hence the error message.
See the API on the sidebar in react-router docs.
Browser Router
<BrowserRouter>
basename: string
getUserConfirmation: func
forceRefresh: bool
keyLength: number
children: node
Router
<Router>
history: object
children: node
https://reacttraining.com/react-router/web/api/Router/history-object
As for the no match, you need a switch and to put the last component without a path. Right now you are grabbing every route with path="*"
Again, see docs https://reacttraining.com/react-router/web/example/no-match
<Switch>
<Route path="/" exact component={Home}/>
<Redirect from="/old-match" to="/will-match"/>
<Route path="/will-match" component={WillMatch}/>
<Route component={NoMatch}/>
</Switch>
I have mixed content on my homepage. The user specific content is an edit button next to their own content.
When the user logs out via a logout route this code gets executed:
import React from 'react'; // needed
import ReactDOM from 'react-dom';
import Home from './components/layout/Home.js';
import Login from './Login/Login';
import PollDetails from './components/layout/PollDetails.js';
import EditPoll from './components/presentation/EditPoll.js';
import CreatePoll from './components/presentation/CreatePoll';
import Container from './components/containers/Container.js';
import {Route,Router,browserHistory,IndexRoute} from 'react-router';
import Auth from './utils/Auth';
const mountNode = document.getElementById('root');
ReactDOM.render(
<Router history={browserHistory}>
<Route path="/" component={Container} >
<IndexRoute component={Home} />
<Route path="login" component={Login} />
<Route path="logout" onEnter={(nextState, replace) => {
Auth.deauthenticateUser();
console.log('Logging out src/app.js');
Auth.clearCookie();
// change the current URL to /
replace('/');}} />
<Route path="Polldetailfull/:id" component={PollDetails} />
<Route path="Editthepoll/:id" component={EditPoll} />
<Route path="createPoll" getComponent={(location, callback) => {
if (Auth.isUserAuthenticated()) {
callback(null, CreatePoll);
} else {
callback(null, Home);
}
}} />
</Route>
</Router>,mountNode);
However, the replace('/'); sends you back to the home page but doesn’t re-render any components. Note there is no state to change here. Do I need a state to force the re-render?
Note, if you press refresh on the browser the desired behaviour happens. I tried looking on React Router's code but could not find much about events. To be honest, I don't fully understand onEnter={(nextState, replace) =>
You could use location.reload() to cause it to re-render
onEnter -> this function use when component going to render on browser.
For your idea, You need to use route the component based log details in component life cycle of particular components.below code to be use in path component life cycle(componentWillMount or componentDidMount) and route the page as want .
browserHistory.push('/location-path-name');
call the component based log details in router like below sample
<Route path="createPoll" component={Auth.isUserAuthenticated() ? CreatePoll : Home}/>