简体   繁体   English

如果路径相同,但参数不同,React-Router 不会接收道具?

[英]React-Router not receiving props if it's the same path, but different param?

I have a path /player/:id/我有一个路径/player/:id/

If I navigate from say /player/12 to /player/13 it will error out, for example: cannot find foo of undefined .如果我从/player/12导航到/player/13它会出错,例如: cannot find foo of undefined However if I navigate from a different path such as /heroes/100 to /player/12 it will load fine.但是,如果我从不同的路径(例如/heroes/100导航到/player/12 ,它将正常加载。

My suspicion is that when I link from the same route, but different param, the new page is not invoking my useEffect or setState hooks.我的怀疑是,当我从相同的路由链接但不同的参数时,新页面不会调用我的 useEffect 或 setState 钩子。

I feel like I'm missing something fundamental here, but I can't figure it out.我觉得我在这里遗漏了一些基本的东西,但我无法弄清楚。 If my suspicion is correct, does anyone know how i can force my component to use my UseEffect and UseState hooks before loading the page when going from the same route, but different params?如果我的怀疑是正确的,有谁知道我如何强制我的组件在从相同的路径但不同的参数加载页面之前使用我的 UseEffect 和 UseState 钩子?

The params are correct, it's displaying the correct id in the url bar.参数是正确的,它在 url 栏中显示了正确的 id。 If i refresh the page it'll load fine, but if i click the link it'll error out Cannot read property 'hero_id' of undefined如果我刷新页面,它会正常加载,但如果我点击链接,它会出错Cannot read property 'hero_id' of undefined

Thank you谢谢

Context:语境:

playedAgainst.map(player => <Link key={Math.random()} to=
{"/players/" + props.invertedPlayers[player]}> <span> {player} </span></Link>

Each iteration creates a new Player name, with a Link.每次迭代都会创建一个带有链接的新玩家名称。 When i click on that link it says all "cannot read property hero_id of undefined".当我单击该链接时,它显示所有“无法读取未定义的属性 hero_id”。 However, when i refresh the page it loads fine.但是,当我刷新页面时,它可以正常加载。 I'm 100% sure the link path is correct.我 100% 确定链接路径是正确的。 I used the exact same code in a different component that leads to the Player component.我在导致 Player 组件的不同组件中使用了完全相同的代码。

(The Math.random is definitely sloppy, i'll remove that!) (Math.random 绝对是草率的,我会删除它!)

        <Header />
        <Switch>
          <Route exact path="/">
            <Search players={this.state.players} />
            <GameList players={this.state.players} data={this.state.games} />
            <Footer />
          </Route>
          <Route exact path="/players/:id">
            <Player players={this.state.players} invertedPlayers = {_.invert(this.state.players)} />
          </Route>
          <Route exact path="/heroes/:id">
            <Heroes players={this.state.players} invertedPlayers = {_.invert(this.state.players)} />
          </Route>
        </Switch>
        </Router>

EDIT -编辑 -

I added the following hook to my Players component.我将以下钩子添加到我的 Players 组件中。

  useEffect(() => {
    console.log('useEffect fired');
}, [])

When i go from 1 id to another (same route, different param) the useEffect hook is not firing.当我从 1 id 转到另一个(相同的路线,不同的参数)时, useEffect 钩子不会触发。

Seems like i need to get my useEffect to fire when following the same routes with different ids.似乎我需要在遵循具有不同 ID 的相同路线时触发我的 useEffect。

Accessing my Params via useParams():通过 useParams() 访问我的参数:

let { id } = useParams();
  const [player, setPlayerData] = useState({ data: null, image: null });
  useEffect(() => {
    const fetchData = async () => {
      const response1 = await axios(`/api/players/${id}`);
      const response2 = await axios(`/api/saveImage/${id}`)
      setPlayerData({ data: response1.data, image: response2.data });
    };
    fetchData();
  }, []);

EDIT 2 -编辑 2 -

Added to ID to useEffect, but useEffect is still not rerunning for some reason:将 ID 添加到 useEffect 中,但由于某些原因,useEffect 仍然没有重新运行:

let { id } = useParams();
  const [player, setPlayerData] = useState({ data: null, image: null });
  useEffect(() => {
    const fetchData = async () => {
      const response1 = await axios(`/api/players/${id}`);
      const response2 = await axios(`/api/saveImage/${id}`)
      setPlayerData({ data: response1.data, image: response2.data });
    };
    fetchData();
  }, [id]);

EDIT 3 -编辑 3 -

More context, hopefully this helps:更多上下文,希望这有助于:

As soon as the component loads it pulls data from the API to load within the component.组件加载后,它会从 API 中提取数据以在组件内加载。 This works fine.这工作正常。 When i click a ling to the same route, but different param, the useEffect hook to pull data doesn't run.当我单击相同路线但不同参数的 ling 时,用于拉取数据的 useEffect 钩子不会运行。

const Player = (props) => {
  let { id } = useParams();
  const [player, setPlayerData] = useState({ data: null, image: null });
  useEffect(() => {
    const fetchData = async () => {
      const response1 = await axios(`/api/players/${id}`);
      const response2 = await axios(`/api/saveImage/${id}`)
      setPlayerData({ data: response1.data, image: response2.data });
    };
    fetchData();
  }, [id]);

  useEffect(() => {
    console.log('count changed');
}, [])

  console.log('test')
    return (
        <div className="historyContainer">
...............

{player.data && player.data.map((game, i) => {
    const heroIdOfPlayer = game.players.find(p => p.account_id === +id).hero_id; 
    const teamOfPro = game.players.find(p => p.hero_id === +heroIdOfPlayer).team;

The part under the '.......' is where Cannot read property 'hero_id' of undefined is coming from, which only happens when clicking through the link. '.......' 下的部分是Cannot read property 'hero_id' of undefined来源,这仅在单击链接时发生。

A few lines further down:再往下几行:

{playedAgainst ?
            playedAgainst.map(player => <Link key={Math.random()} to={"/players/" + props.invertedPlayers[player]}><span> {player} </span></Link>)
            : ""}

This is how each link is generated.这就是每个链接的生成方式。 The path is correct.路径是正确的。 if i follow the path it'll say Cannot read property 'hero_id' of undefined , but when i refresh the page it will load fine.如果我按照路径,它会说Cannot read property 'hero_id' of undefined ,但是当我刷新页面时,它将正常加载。

EDIT - 4编辑 - 4

Adding my App component in case this helps:添加我的 App 组件以防万一:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      games: [],
      players: {},
    };
  }



  componentDidMount() {
    ReactGA.pageview(window.location.pathname)
    this.loadGames();
    this.loadPlayers();
    this.interval = setInterval(() => {
      this.loadGames();
    }, 5000);

  }

  componentWillUnmount() {
    this.loadGames();
    clearInterval(this.interval);
  }

  async loadGames() {
    const response = await fetch('/api/games');
    const myJson = await response.json();
    const sortedJson = myJson.sort((a, b) =>
      a.spectators > b.spectators ? -1 : 1,
    );
    this.setState({ games: sortedJson });
  }

  async loadPlayers() {
    const response = await fetch('/api/playersList');
    const myJson = await response.json();
    this.setState({ players: myJson });
  }

  render() {
    return (
      <Router history={history}>
        <Header />
        <Switch>
          <Route exact path="/">
            <Search players={this.state.players} />
            <GameList players={this.state.players} data={this.state.games} />
            <Footer />
          </Route>
          <Route exact path="/players/:id">
            <Player players={this.state.players} invertedPlayers = {_.invert(this.state.players)} />
          </Route>
          <Route exact path="/heroes/:id">
            <Heroes players={this.state.players} invertedPlayers = {_.invert(this.state.players)} />
          </Route>
        </Switch>
        </Router>
    );
  }
}


ReactDOM.render(<App />, document.getElementById('app'));

In your useEffect hook, pass the prop that changes as a dependency ie在您的useEffect钩子中,将更改为依赖项的 prop 传递,即

useEffect(..., [id])

This will ensure useEffect runs everytime id changes, the problem at the minute is you pass [] which means useEffect will only run once, when the component is first mounted.这将确保useEffect在每次id更改时运行,目前的问题是您传递[]这意味着useEffect只会在组件首次安装时运行一次。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM