1

react-router-dom v5 and React 16

My loading app component contains:

ReactDOM.render(
  <FirebaseContext.Provider value={new Firebase()}>
    <BrowserRouter>
      <StartApp />
    </BrowserRouter>,
  </FirebaseContext.Provider>,
  document.getElementById("root")
);

I have a route component which contains:

  {
    path: "/member/:memberId",
    component: MemberForm,
    layout: "/admin"
  },

Admin component:

return (
  <>
    <div className="main-content" ref="mainContent">
      <LoadingComponent loading={this.props.authState.loading}>
      <AdminNavbar
        {...this.props}
        brandText={this.getBrandText(this.props.location.pathname)}
      />
      <AuthDetailsProvider>
        <Switch>{this.getRoutes(routes)}</Switch>
      </AuthDetailsProvider>
      <Container fluid>
        <AdminFooter />
      </Container>
      </LoadingComponent>
    </div>
  </>
)

this.getRoutes in the Switch contains the reference route above.

Now from one of my component pages I can navigate to /member/{memberid} this works fine.

the route loads a component called MemberForm inside MemberForm I have a row that contains this method:

              <Row>
              { this.displayHouseholdMembers() }
              </Row>


  displayHouseholdMembers = () => {
    const householdDetails = this.state.family;
    if (householdDetails) {
      return householdDetails.map((key, ind) => {
        if (key['uid'] != this.state.memberKeyID) {
          return (
            <Row key={ind} style={{ paddingLeft: '25px', width: '50%'}}>
              <Col xs="5">
                <Link to={ key['uid'] }>
                  { key['first'] + " " + key['last'] }
                </Link>
              </Col>
              <Col xs="4">
                { key['relation'] }
              </Col>
              <Col xs="3">
                <Button
                  color="primary"
                  size="sm"
                  onClick={(e) => this.removeHouseRelation(key)}
                >
                  Remove
                </Button>
              </Col>
            </Row>
          );
        }
      });
    }
  };

MemberForm: in componentDidMount I do an firebase call to check for the data pertaining to the user using the uid aka memberId in the URL.

class MemberForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      ...INITIAL_STATE,
      currentOrganization: this.props.orgID,
      householdRelation: ['Spouse', 'Child', 'Parent', 'Sibling'],
      householdSelected: false,
    };
  }

  componentDidMount() {
    let urlPath, personId;

      urlPath = "members";
      personId = this.props.match.params.memberId;
      // if it is a member set to active
      this.setState({ statusSelected: "Active" })
      this.setState({ memberSaved: true, indiUid: personId });

    // this sets visitor date for db
    const setVisitorDate = this.readableHumanDate(new Date());

    this.setState({ formType: urlPath, visitorDate: setVisitorDate }, () => {
      if (personId) {
        this.setState({ memberSaved: true, indiUid: personId });
        this.getIndividualMemberInDB(
          this.state.currentOrganization,
          personId,
          this.state.formType,
          INITIAL_STATE
        );
      }
    });
  }
...
    return (
      <>
        <UserHeader first={s.first} last={s.last} />
        {/* Page content */}
        <Container className="mt--7" fluid>
          <Row>
 ...
                      <Row>
                      { this.displayHouseholdMembers() }
                      </Row>
                    </Form>
                  </CardBody>
                ) : null}
              </Card>
            </Col>
          </Row>
          <Row>
          <Col lg="12" style={{ padding: "20px" }}>
            <Button
              color="primary"
              onClick={e => this.submitMember(e)}
              size="md"
            >
              Save Profile
            </Button>
            { this.state.indiUid ? (
              <Button
                color="secondary"
                onClick={e => this.disableProfile()}
                size="md"
              >
                Disable Profile
              </Button>
            ) : null }
          </Col>
          </Row>
        </Container>
      </>
    );

When I click on the Link it shows the url has changed 'members/{new UID appears here}' but the page does not reload. I believe what's going on is that since it's using the same route in essence: path: "/member/:memberId"it doesn't reload the page. How can I get it to go to the same route but with the different memberId?

7
  • What exact version of react-router-dom@5 is installed, and what version of React are you using, React 18? Does this help answer your question? stackoverflow.com/a/71833424/8690857 Can you edit your post to include all the relevant code, including the routes you are rendering? See minimal reproducible example. Commented Jul 1, 2022 at 4:42
  • "react": "^16.12.0", "react-router-dom": "5.3.3" @DrewReese ok I'll add minimum working example Commented Jul 1, 2022 at 5:35
  • After digging into this I realized this isn't a LInk issue. The challenge is that I'm on the same page aka component only with a different dynamic tag which pulls data related to the dynamic parameter on the page. @DrewReese Commented Jul 1, 2022 at 7:08
  • I see. Can you share the more complete code example then? The route rendering the component and the dynamic "tag" you need to process? Commented Jul 1, 2022 at 7:10
  • I updated but not sure if I explained it right THANK YOU! @DrewReese Commented Jul 1, 2022 at 18:49

2 Answers 2

1

You are correct that the MemberForm component remains mounted by the router/route when only the path param is updating. Because of this the MailForm component needs to handle prop values changing and re-run any logic depending on the prop value. The componentDidUpdate is the lifecycle method to be used for this.

Abstract the logic into a utility function that can be called from both componentDidMount and componentDidUpdate.

Example:

getData = () => {
  const urlPath = "members";
  const { memberId } = this.props.match.params;

  // this sets visitor date for db
  const setVisitorDate = this.readableHumanDate(new Date());

  this.setState(
    {
      // if it is a member set to active
      statusSelected: "Active",
      memberSaved: true,
      indiUid: memberId,
      formType: urlPath,
      visitorDate: setVisitorDate
    },
    () => {
      if (memberId) {
        this.setState({ memberSaved: true, indiUid: memberId });
        this.getIndividualMemberInDB(
          this.state.currentOrganization,
          memberId,
          this.state.formType,
          INITIAL_STATE
        );
      }
    }
  );
}

The lifecycle methods:

componentDidMount() {
  this.getData();
}

componentDidUpdate(prevProps) {
  if (prevProps.match.params.memberId !== this.props.match.params.memberId) {
    this.getData();
  }
}
Sign up to request clarification or add additional context in comments.

Comments

0

For react-router-dom v6, can you try with simple routing? Create a Test.js with

const Test = ()=> <h1>Test Page</h1>

Then, create a Home.js with

const Home = ()=> <Link to="/test">Test</Link>

Then, add them to route.

<BrowserRouter>
    <Routes>
      <Route path="/" element={<Home/>} />
      <Route path="/test" element={<Test />} />
    </Routes>
  </BrowserRouter>

Does your component structure look like this? For index route, look more at https://reactrouter.com/docs/en/v6/getting-started/overview.

Comments

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.