javascript - 如果路径相同但参数不同,React-Router 不接收道具?
问题描述
我有一条路/player/:id/
如果我从 say 导航/player/12
到/player/13
它会出错,例如:cannot find foo of undefined
. 但是,如果我从不同的路径导航/heroes/100
到/player/12
它会加载正常。
我的怀疑是,当我从同一路由链接但参数不同时,新页面不会调用我的 useEffect 或 setState 挂钩。
我觉得我在这里遗漏了一些基本的东西,但我无法弄清楚。如果我的怀疑是正确的,有谁知道我可以如何强制我的组件在从同一路线但不同的参数加载页面之前使用我的 UseEffect 和 UseState 钩子?
参数是正确的,它在 url 栏中显示正确的 id。如果我刷新页面它会加载正常,但如果我点击链接它会出错Cannot read property 'hero_id' of undefined
谢谢
语境:
playedAgainst.map(player => <Link key={Math.random()} to=
{"/players/" + props.invertedPlayers[player]}> <span> {player} </span></Link>
每次迭代都会创建一个带有链接的新玩家名称。当我单击该链接时,它显示所有“无法读取未定义的属性 hero_id”。但是,当我刷新页面时,它加载正常。我 100% 确定链接路径是正确的。我在通向 Player 组件的不同组件中使用了完全相同的代码。
(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>
编辑 -
我在我的 Players 组件中添加了以下钩子。
useEffect(() => {
console.log('useEffect fired');
}, [])
当我从 1 个 id 转到另一个(相同的路线,不同的参数)时,useEffect 钩子没有触发。
似乎我需要让我的 useEffect 在遵循具有不同 ID 的相同路线时触发。
通过 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();
}, []);
编辑 2 -
将 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]);
编辑 3 -
更多上下文,希望这会有所帮助:
一旦组件加载,它就会从 API 中提取数据以加载到组件中。这工作正常。当我单击一条到同一路线但参数不同的 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;
“.......”下面的部分Cannot read property 'hero_id' of undefined
是来自哪里,只有在点击链接时才会发生。
再往下几行:
{playedAgainst ?
playedAgainst.map(player => <Link key={Math.random()} to={"/players/" + props.invertedPlayers[player]}><span> {player} </span></Link>)
: ""}
这就是每个链接的生成方式。路径是正确的。如果我按照它会说的路径Cannot read property 'hero_id' of undefined
,但是当我刷新页面时它会加载正常。
编辑 - 4
添加我的 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'));
解决方案
在您的useEffect
钩子中,将更改的道具作为依赖项传递,即
useEffect(..., [id])
这将确保useEffect
每次id
更改时都运行,此时的问题是您通过了[]
,这意味着useEffect
在首次安装组件时只会运行一次。
推荐阅读
- asp.net-web-api - 如何在 Web API 中使用 Azure CloudQueueClient?
- python - Salt:在 salt minion 上激活虚拟环境
- php - 在 laravel 5.6 中的路由上定义自定义命名空间
- swift - firebase 照片丢失时崩溃
- android - 进程运行时如何显示进度条?
- spring - 自定义 Spring Boot 控制器,支持异常处理
- postgresql - “错误:类型“pg_catalog.varchar_latin”不存在”
- http - Httpd Proxy Server 2.4.33 版本 Worker 名称?
- objective-c - __bridge_transfer 和 CFBridgingRelease 在 ARC 代码中有不同的结果
- python - 显示来自 ADC 的平均数据的问题