I was originally using hashHistory from react-router and programmatically navigating my React app using this.props.history.push(). But with the move to using HashRouter from the react-router-dom package, this.props.history.push() now throws a Cannot read property 'push' of undefined error.
How do I programmatically navigate using HashRouter now?
ReactDOM.render(
<Provider store={store}>
<MuiThemeProvider>
<HashRouter>
<div>
<Route exact path="/" component={App} />
<Route path="/landing" component={Landing} />
</div>
</HashRouter>
</MuiThemeProvider>
</Provider>,
document.getElementById('root'));
Render func of App.js
render() {
return (
<div className="App">
...
<div>
<Collapse isOpened={this.state.activeForm === 1}>
<SignUpForm />
</Collapse>
<Collapse isOpened={this.state.activeForm === 2}>
<SignInForm />
</Collapse>
...
</div>
);
}
Function in SignUpForm.js that's calling .push()
handleSubmit(e) {
...
this.props.history.push('/landing');
...
}
If your component is rendered from a Route (like App and Landing), then you will have access to all router related props (match, history, location). However, since SignUpForm isn't rendered with a Route, you won't have access to those props by default.
But we can use withRoute higher-order component to explicitly get those props. We just need to wrap the component with this HoC before exporting it as follows.
export default withRouter(SignUpForm);
Now it will work as expected since SignUpForm gets history prop.
I have figured out what my issue is. My index.js is set up as such (below) with App.js as one of the routes, not SignUpForm.js, which is a container being rendered in App.js. This means that SignUpForm.js has no notion of the history prop within App.js.
By passing App.js's history prop to SignUpForm.js as a prop, I was able to call this.props.history.push() within SignUpForm.js to get my desired action.
Related
I think it's because I'm using the latest version of react and they have changed many components, since. All I want to do is navigate to another page.
I tried wrapping it it
<Routes>
<button
className="whatevr"
onClick={() => {
navigate("../FeaturePage");
}}
>
Features
</button>
</Routes>
Based on both errors regarding the use of the useNavigate and useRoutes hooks both needing to be used within a routing context, i.e. called with in a <Router> component, it seems that you are not actually doing this.
Render the app, or these specific components within a router.
Example:
const App = () => (
<>
<Navbar />
<Routes>
<Route path="/" .... />
... other routes ...
</Routes>
</>
);
Parent component rendering App.
<BrowserRouter>
</App />
</BrowserRouter>
I have a react app, and a component that is supposed to load a set of value of the url
<PersistGate persistor={rootStore.persistor}>
<Router history={history}>
<ErrorBoundary>
<Preloader history={history} /> <== this need to read the url
<PasswordChecker></PasswordChecker>
<RouteDispatcher></RouteDispatcher> <== this contain the list of routes
</ErrorBoundary>
</Router>
</PersistGate>
In my RouteDispatcher path I have setup the route like this :
<BrowserRouter>
<Switch>
<PrivateRoute path="/ws/:ws/pj/:pj/ds/:ds" component={HomeDatastore} />
<PrivateRoute path="/ws/:ws/pj/:pj" component={HomeProject} />
<PrivateRoute path="/ws/:ws" component={HomeWorkspace} />
</Switch>
</BrowserRouter>
how would I get the value of ws=:ws pj=:pj etc...
I was thinking of doing it with a regex, but I wonder if there is a better way. Preloader is outside the routeDispatcher, so I don't seem to find a good way to get the value.
React router provides params into the component. Check props.match.params. I see that you have a custom component PrivateRoute so first check props in PrivateRoute.
May be try using useParams() hook. It gives you a way to access the URL params
Reference: https://blog.logrocket.com/react-router-hooks-will-make-your-component-cleaner/
Sandbox: https://codesandbox.io/s/react-router-useparams-hooks-q8g37
This might help you get started with it
import { useParams } from "react-router-dom";
function ComponentName() {
let params = useParams();
return (
<div>
{params.ws}
{params.pj}
</div>
);
}
I'm trying to toggle a few components based on route. I do get it to work on a refresh but not a navigate. Anybody know what I'm missing and doing wrong here?
import { BrowserRouter as Router, withRouter } from "react-router-dom";
class App extends Component {
render() {
return (
<Router>
<div className="App">
pathname: {(this.props.location.pathname)}
{!this.props.location.pathname.includes('/target') ? <TopBar childProps={childProps} /> : null}
{!this.props.location.pathname.includes('/target') ? <Header /> : null}
{this.props.location.pathname.includes('/target') ? <SecondaryHeader /> : null}
<Routes childProps={childProps} />
<Footer />
</div>
</Router>
)
}
}
export default withRouter(App)
There is a component exported from react-router-dom which is called Route, and it encapsulates exactly the logic you want.
Conditionally renders components based on the current path
<Router>
<Route path='/target' render={() => <MyComponent />} />
<Route exact path='/target' render={() => <AnotherComponent />} />
</Router>
render accepts a function which returns some jsx (you can also use component, see the differences here).
path is the path that window.location.pathname must match to render what is being passed to render or component
exact is whether or not the path must be absolute.
Imagine that the current path is /target/foo. In this case MyComponent will be rendered but AnotherComponent won't.
You can also pass a regex to path, see the full docs here
i'm using react-redux in my project.
I have some component where i'm dispatch some action and get data from reducer into a component on componentWillMount method here is problem when i change to route componentWillMount method not firing my actions or anything else. for that i need to refresh page.
here is my componentWillMount Method:
componentWillMount() {
console.log("d")
this
.props
.getChartData()
data = this.props.chartData
}
and here is my main.js where i import my components and assign routing.
import CompA from 'components/CompA'
import CompB from 'components/CompB'
const App = () => (
<Container fluid>
<div>
<main>
<Switch>
<Route exact path="/page-a" component={ComponentA} />
<Route exact path="/page-b" component={ComponentB} />
</Switch>
</main>
</div>
</Container>
)
export default App
where i mistake or what i need to do with it?
and its index.js:
const target = document.querySelector('#root')
console.log(store.getState())
render(
<Provider store={store}>
<ConnectedRouter history={history}>
<div className="row">
<App />
</div>
</ConnectedRouter>
</Provider>,
target
)
if you use redux you should use mapStateToProps to change the state in your component
I think you are using ConnectedRouter from the package react-router-redux, which is now deprecated.
For react-router 4, You need to use withRouter react-router-dom to wrap the component before connecting it like this:
withRouter(connect(...)(MyComponent))
You can get also get the match, location, history properties via props once the component is wrapped in withRouter.
For further information on withRouter, you can visit the following link: https://reacttraining.com/react-router/web/api/withRouter
I've seen problems like this but neither of them solved my problem.
I have a p tag that onClick is supposed to render a page.
But when I click on it and use this.props.history.push(/posts/${id}) It changes the url but doesn't render the component I want.
I have tried using a
onClick={(e, id) => this.postPage(e, post.id)}
to trigger a function that will trigger the component I want to show up. I also tried using
<Link to-=''>
insted of
<p onClick>
but it doesn't work either.
This is what I have done so far, this is the function that triggers when I click the p tag:
postPage = (e, id) => {
const { history } = this.props;
history.push(`/post/${id.toString()}`);
}
and also, I used withRouter to have access to the history prop.
export default withRouter(connect(null, mapDispatchToProps)(Post));
And these are the routes I mapped:
render() {
return (
<div className="Routes">
<Switch>
<Route exact path='/' component={Home}></Route>
<Route path='/post/:id' render={(history) => (
<PostPage {...history}></PostPage>
)}></Route>
</Switch>
</div>
);
}
}
And of course, when I call this component I also pass using BrowserRouter
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<Routes />
</BrowserRouter>
</Provider>
, document.getElementById('root'));
I just wanted to render the component but only the URL changes and nothing happens.
A good approach would be to implement react-redux and react-router-dom one at a time, to ensure that there are no clashes. The double HOC here:
export default withRouter(connect(null, mapDispatchToProps)(Post));
Is worth breaking down to:
export default withRouter(Post);
To ensure that react-router-dom works as expected, then implementing react-redux once routing is in place.
For those who have had the same problem the solution was to change the BrowserRouter tag location from the index.js to inside of the component that uses the Route. I was doing something like:
ReactDOM.render(<Provider>
<BrowserRouter>
<App>
</BrowserRouter>
</Provider>, document.getElementById('root'));
and now inside the Routes.js component
render() {
<BrowserRouter>
<Route ...>
<Route ...>
</BrowserRouter>
}