3

I'm building a React app where I do NOT want the URL in the browser to be updated. I am NOT using 'react-router-dom' but only 'react-router' and MemoryRouter (https://reacttraining.com/react-router/web/api/MemoryRouter). The history.push() is available directly in the component statements but I wish to pass the history to children of children of these main components but the property is undefined.

Here is the Router section in main App.js (components Home and ScreeningTool can access this.props.history.push() as expected):

...
import {Route, MemoryRouter} from "react-router";
...
<MemoryRouter>
    <Route exact path="/" component={Home} />
    <Route path="/screening-tool" component={ScreeningTool} />
</MemoryRouter>
... 

Both Home and ScreeningTool both use child component AppLink that generates a 'link' to navigate between Home and ScreeningTool like so (notice I'm passing 'history' as a prop):

Home.js:
...
<AppLink
    url="/"
    label="Screening Tool"
    history={this.props.history}
/>
...

AppLink.js:
...
<div className="pseudo-link">
    <span onClick={() => this.props.history.push(this.props.url)}>
        {this.props.label}
    </span>
</div>
...

The above code works. But there are children components in Home that will create their own AppLinks and also greatgrandchildren. I do NOT want to pass the history property as a component prop from Parent to Child to GrandChild components because this does not seem efficient. I have found the following stackoverflow questions but none of these options are working for me:

this.props.history.push works in some components and not others

react-router getting this.props.location in child components

I tried the newer 'userHistory' as described in the second URL above:

...
import { useHistory } from 'react-router';
...
render() {
    let history = useHistory();
    return (
        <div className="pseudo-link">
            <span onClick={() => history.push(this.props.url)}>
                {this.props.label}
            </span>
        </div>
    );
}
...

but I get Error: Invalid hook call. Hooks can only be called inside of the body of a function component..

I tried using withRouter as defined here https://reacttraining.com/react-router/web/api/withRouter but I get Error: Invariant failed: You should not use <withRouter(PseudoLink) /> outside a <Router>.

Finally, the accepted answer for this.props.history.push works in some components and not others ends with block of code export default withRouter(connect(mapStateToProps, matchDispatchToProps)(ChildView)); but does not explain where mapStateToProps or matchDispatchToProps comes from?

I'm thinking the issue is that I am using MemoryRouter and not normal/most common Router from 'reacto-router-dom'.

Can anyone help me out?

1 Answer 1

2

useHistory is a Hook so it should be used in a functional component, not inside a class based component.

Finally, the accepted answer for this.props.history.push works in some components and not others ends with block of code export default withRouter(connect(mapStateToProps, matchDispatchToProps)(ChildView)); but does not explain where mapStateToProps or matchDispatchToProps comes from?

-If you're not using redux then you can just use

export default withRouter(yourComponentName);

update

I've changed the AppLink component to this and it is working fine

import React from "react";
import "./AppLink.css";
import { useHistory } from 'react-router';

const AppLink = props => {
  const history = useHistory();
  return (
    <div
      className="app-link-button"
      onClick={() => history.push(props.url)}
    >
      <span>{props.label}</span>
    </div>
  );
};

export default AppLink;
Sign up to request clarification or add additional context in comments.

10 Comments

I have changed the class component to be functional but get error still at useHistory() 'TypeError: Cannot read property 'history' of undefined'
as far as withRouter() I explain above that i already used that and I included the error.
@PippyLongstocking Make sure all the elements that use withRouter are wrapped with BrowserRouter docs
Ramesh, import React from 'react'; import { useHistory } from "react-router"; import './AppLink.scss'; const AppLink = (props) => { let history = useHistory(); console.log('HISTORY:::', history); return ( <div className="pseudo-link"> <span onClick={() => history.push(props.url)}> {props.label} </span> </div> ); } export default AppLink; Also, I am not using react-router-dom where BrowserRouter seems to come from. I"m only using 'react-router'
Ramesh, I do not know what you mean. This is a child component to show a label to navigate between the parent compents, and those parent components are wrapped by Router as I poseted code above....can you provide example?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.