FabricioG
FabricioG

Reputation: 3320

Link in react router dom doesn't load page only url browser nav gets changed

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?

Upvotes: 1

Views: 723

Answers (2)

Drew Reese
Drew Reese

Reputation: 203457

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();
  }
}

Upvotes: 1

Four
Four

Reputation: 1084

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.

Upvotes: 0

Related Questions