Abhilash
Abhilash

Reputation: 895

React router is not mounting the component

I'm using React Router for routing to different routes as below:

     <Router>
        <Switch>
        <Route path="/teams/:teamName/matches" >
          <MatchPage/>
        </Route>  
        <Route path="/teams/:teamName" >
          <TeamPage/>
        </Route>
        </Switch>
      </Router>

Now in my TeamPage component I'm calling an API using async and then in the render method invoking another component called MatchDetailCard

class TeamPage extends Component {
    constructor(props) {
        console.log('const called')
        super(props)
        this.state = { 
            team: [],
            teamName:null
        }
    }

    async componentDidMount() {
        console.log(this.props.match.params.teamName);
        const teamName = this.props.match.params.teamName;
        const response = await fetch(`http://localhost:8080/team/${teamName}`);
        const json = await response.json();
        console.log(json);
        this.setState({team:json, teamName: teamName});
    }

    componentDidUpdate () {
        console.log('updated')
    }

    render() {
        if (!this.state.team || !this.state.team.teamName) {
            return <h1>Team not found</h1>;
        }
        return (
            <div className="TeamPage">
            <div className="match-detail-section">
                <h3>Latest Matches</h3>
                <MatchDetailCard teamName={this.state.team.teamName} match={this.state.team.matches[0]}/>
            </div>
            </div>
        );
    }
}

export default withRouter(TeamPage);

Within the MatchDetailCard component I create a router Link to the same TeamPage component which will have a different teamName this time as below:

const MatchDetailCard = (props) => {
    if (!props.match) return null;
    const otherTeam = props.match.team1 === props.teamName ? props.match.team2 : props.match.team1;
    const otherTeamRoute = `/teams/${otherTeam}`;
    const isMatchWon = props.teamName === props.match.matchWinner;
    return (
      <div className={isMatchWon ? 'MatchDetailCard won-card' : 'MatchDetailCard lost-card'}>
        <div className="">
            <span className="vs">vs</span><h1><Link to={otherTeamRoute}>{otherTeam}</Link></h1>
        </div>
      </div>
    );
  }
  
  export {MatchDetailCard};

The problem that I'm facing is that the on-click of the link to /team/teamName route only the TeamPage component is not mounting instead it's just getting an update.

I want to have the call to componentDidMount hook to make the API call again in this scenario.

What's the problem with my logic?

Upvotes: 1

Views: 1380

Answers (1)

Benjamin
Benjamin

Reputation: 3656

If the same component is used as the child of multiple <Route>s at the same point in the component tree, React will see this as the same component instance and the component’s state will be preserved between route changes. If this isn’t desired, a unique key prop added to each route component will cause React to recreate the component instance when the route changes.

https://reactrouter.com/web/api/Route

You can add the teamName as a key prop on the component, which will tell React to unmount/mount the component when the key value changes.

<Router>
  <Switch>
    <Route
      path="/teams/:teamName/matches"
      render={({ match }) => {
        return <MatchPage key={match.params.teamName} />;
      }}
    />
    <Route
      path="/teams/:teamName"
      render={({ match }) => {
        return <TeamPage key={match.params.teamName} />;
      }}
    />
  </Switch>
</Router>

Upvotes: 5

Related Questions