Reputation: 1222
I have a page component SimulationReport
that I want to redirect to upon clicking a button from the Reports
page component. This is the App
component with the Router
:
function App() {
return (
<React.Fragment>
<Router>
<NavigationBar />
<Sidebar />
<Switch>
<Route exact path="/" component={Ratings} />
<Route path="/LeagueSettings" component={LeagueSettings} />
<Route path="/Fixtures" component={Fixtures} />
<Route path="/Reports" component={Reports} />
<Route path="/SimulationReport" component={SimulationReport} />
</Switch>
</Router>
</React.Fragment>
);
}
And here are the relevant code bits from Reports
which is a function component:
import {withRouter} from "react-router-dom";
<td>
<Button variant="primary" onClick={handleSimView(index)}>
View
</Button>
</td>
const handleSimView = index => e => {
console.log("index: " + index);
loadSimulationResult(simulationIds[index]);
props.history.push("/SimulationReport");
};
And at the end of the file I have this:
export default withRouter(Reports);
Upon clicking the button, I receive this error:
TypeError: Cannot read property 'push' of undefined
I'm not sure what I need to do to redirect this? Or maybe I should be doing it a different way?
Upvotes: 0
Views: 96
Reputation: 133
Seems that your prop history
is not being passed from the <Route>
tag in your component.
You can pass props to a Route Rendered Component by doing the following line:
<Route
path='/SimulationReport'
render={(props) => <SimulationReport {...props} history={yourHistoryObjectForTheRouter} />}
/>
where yourHistoryObjectForTheRouter would be your custom history exported object.
EDIT: Updated code
UPDATE TO ANSWER TO ADDRESS OP's NEEDS:
1° Alright, so first you'll need to install the package called history
to your React Application. (You can use npm i history
or yarn add history
. It depends on what you have installed. If you don't know what's yarn then use the npm option)
2° Somewhere in your project inside the App folder (src/App/), you're going to create another folder called history
and inside index.js
.
The contents of the index.js
file are going to be the next ones.
import { createBrowserHistory } from 'history';
export default createBrowserHistory({});
3° Once that is done, head to your App/index.js
file, where you have your <Router>
main tag. If you've done everything as I stated before, in that App/index.js
you're going to add a new import:
import history from "./history";
Which is your new Custom History Object.
Here you can choose two paths of how you want to solve your problem
=== First Solution
4° Scroll down in that same file, until you find your <Router></Router>
tag, and you're going to update it to this next part:
<Router>
<NavigationBar />
<Sidebar />
<Switch>
<Route exact path="/" component={Ratings} />
<Route path="/LeagueSettings" component={LeagueSettings} />
<Route path="/Fixtures" component={Fixtures} />
<Route path="/Reports" component={Reports} />
<Route
path='/SimulationReport'
render={(props) => <SimulationReport {...props} history=
{history} />}
/>
</Switch>
</Router>
After this, you'll have your Custom History Object setted up and your component now should work.
This solution however will only work for that specific component Route, and that means that you will have to do the same for the other <Route >
that require the use of the history object.
Stop here if you choose this solution.
=== Second Solution
This solution is better, because you'll now have access to your history object globally, just with an import.
4° Scroll down in that same file, until you find your <Router></Router>
tag, and you're going to update it to this next part:
<Router history={history}> //Here's the change
<NavigationBar />
<Sidebar />
<Switch>
<Route exact path="/" component={Ratings} />
<Route path="/LeagueSettings" component={LeagueSettings} />
<Route path="/Fixtures" component={Fixtures} />
<Route path="/Reports" component={Reports} />
<Route path="/SimulationReport" component={SimulationReport} />
</Switch>
</Router>
After this, you'll have your Custom History Object setted up.
5° Navigate to the file that contains the Reports
functional component, and on the imports at the top of your file, you're going to import the same history
as you did in App/index.js
. Beware that depending on the level of subfolders that your Reports components is in, it's how the import is going to change. It can end up like this:
import history from "../history";
or this
import history from "../../history";
it depends or even more "../". It depends on your subfolder levels
After that, you'll need to update your function handleSimView
so instead of doing this:
const handleSimView = index => e => {
console.log("index: " + index);
loadSimulationResult(simulationIds[index]);
props.history.push("/SimulationReport");
};
do this:
const handleSimView = index => e => {
console.log("index: " + index);
loadSimulationResult(simulationIds[index]);
history.push("/SimulationReport"); //Change is here, removed "props."
};
After this, your code should work. This solution you can implement it everywhere as you would only need to import the history object and just use it.
I'll be waiting to hear from you to see if it worked. If anything else happens, you can ask me.
Upvotes: 1