React router dynamiclly

Viewed 27

i am pretty new to react.js, and i wonder how i can accses the browsers query params, example: fetch('http://localhost:8080/api/teamcomp/getPlayersInComp/{id}'). I've tried some soulutions i found on other stackoverflow but i cant make ehm work, here is my code:

 import React from 'react';
import {useParams} from "react-router-dom";

class TeamComponent extends React.Component {
     constructor(props) {

        super(props);

        this.state = {
            players: [],
            isLoaded: false
        }

    }

    componentDidMount() {
        const {player} = useParams()
        fetch('http://localhost:8080/api/teamcomp/getPlayersInComp/{player}')
            .then(res => res.json())
            .then(json => {
                this.setState({
                    players: json,
                    isLoaded: true, 
                })
            }).catch((err) => {
                console.log(err);
            });

    }

    render() {

        const { isLoaded, players } = this.state;

        if (!isLoaded)
            return <div>Loading...</div>;

        return (
            <div className="App">
                <ul>
                    {players.map(player => (
                        <li key={player.id}>
                            Ign: {player.characterName} | Role: {player.role} | Class: {player.classes}
                        </li>
                    ))}
                </ul>
            </div>
        );

    }

}
export default TeamComponent;

and here is the routing:

import React from 'react'
import Home from './Home'
import { BrowserRouter as Router, Route, Switch } from
  'react-router-dom';
import MakeGroupComponent from './MakeGroupComponent';
import TeamComponent from './TeamComponent';

const ReactRouterSetup = () => {
  return (
    <Router>
      <Route exact path='/'>
        <Home />
      </Route>
      <Route exact path='/MakeGroup'>
        <MakeGroupComponent />
      </Route>
      <Route exact path='/Team/:id'>
        <TeamComponent />
      </Route>
    </Router>
  )
}

export default ReactRouterSetup;

any help would be great :D

1 Answers

The TeamComponent needs to access the match prop. The useParams hook is only compatible with functional components. Don't forget to also fix your fetch request url, it should be a string template so you can inject the route match param.

Option 1

Move TeamComponent to the component prop of the Route so route props are passed to it.

<Route
  exact
  path='/Team/:id'
  component={TeamComponent}
/>

Access the match prop.

class TeamComponent extends React.Component {
  ...

  componentDidMount() {
    const { id } = this.props.match.params;
    fetch(`http://localhost:8080/api/teamcomp/getPlayersInComp/${id}`)
      .then(res => res.json())
      .then(json => {
        this.setState({
          players: json,
          isLoaded: true, 
        })
      }).catch((err) => {
        console.log(err);
      });
  }

Option 2

Decorate the TeamComponent export with the withRouter Higher Order Component to have the route props injected. Access the match prop as above.

import { withRouter } from 'react-router-dom';

class TeamComponent extends React.Component {
  ...

  componentDidMount() {
    const { id } = this.props.match.params;
    fetch(`http://localhost:8080/api/teamcomp/getPlayersInComp/${id}`)
      .then(res => res.json())
      .then(json => {
        this.setState({
          players: json,
          isLoaded: true, 
        })
      }).catch((err) => {
        console.log(err);
      });
  }

  ...
}

export default withRouter(TeamComponent);

Option 3

Convert TeamComponent to a functional component.

import { useParams } from "react-router-dom";

const TeamComponent = () => {
  const [isLoaded, setIsLoaded] = useState(false);
  const [players, setPlayers] = useState([]);

  const { id } = useParams();

  useEffect(() => {
    fetch(`http://localhost:8080/api/teamcomp/getPlayersInComp/${id}`)
      .then((res) => res.json())
      .then((json) => {
        setPlayers(json);
      })
      .catch((err) => {
        console.log(err);
      })
      .finally(() => setIsLoaded(true));
  }, []);

  if (!isLoaded) return <div>Loading...</div>;

  return (
    <div className="App">
      <ul>
        {players.map((player) => (
          <li key={player.id}>
            Ign: {player.characterName} | Role: {player.role} | Class:{" "}
            {player.classes}
          </li>
        ))}
      </ul>
    </div>
  );
};
Related