在react中改变url时重新渲染相同的组件

问题描述 投票:0回答:7

我有一条路线,它采用一个 id 并为每个 id 呈现相同的组件,例如:

<Route path='/:code' component={Card}/>

现在,在 Link 标签中,我将 id 传递给组件。现在,Card 组件根据传递的 id 获取其他详细信息。但问题是它仅针对一个 id 呈现,并且如果我单击“后退”并转到下一个 id,则不会更新。我搜索并发现 ComponentsWillReceiveProps 可以使用,但在最近版本的 React 中它已被弃用。那么如何做到这一点呢?

javascript reactjs redux react-router react-props
7个回答
28
投票

将当前位置作为组件的键解决了问题。

<Route path='/:code' component={(props) => <Card {...props} key={window.location.pathname}/>}/>

14
投票

我刚刚遇到了类似的问题。我认为您正在将更新/重新渲染和重新安装混为一谈。 这个有关 React 生命周期方法的图表在我处理它时对我很有帮助。

如果你的问题和我的一样,那么你有一个像

这样的组件

class Card extend Component { componentDidMount() { // call fetch function which probably updates your redux store } render () { return // JSX or child component with {...this.props} used, // some of which are taken from the store through mapStateToProps } }

第一次点击安装此组件的 URL 时,一切正常,然后,当您访问使用相同组件的另一个路由时,没有任何变化。那是因为组件没有被重新安装,它只是因为一些 props 改变而被更新,至少

this.props.match.params

 正在改变。

但是组件更新时不会调用

componentDidMount()

(请参阅上面的链接)。所以你不会获取新数据并更新你的 redux 存储。您应该添加一个 
componentDidUpdate()
 函数。这样你就可以在 props 改变时再次调用你的获取函数,而不仅仅是在组件最初安装时。

componentDidUpdate(prevProps) { if (this.match.params.id !== prevProps.match.params.id) { // call the fetch function again } }

查看反应

文档以获取更多详细信息。


2
投票
我实际上找到了另一种方法来做到这一点。

我们将从您的示例代码开始:

<Route path='/:code' component={Card}/>



你想要做的是让

<Card>

 成为一个包装组件,最好是功能性的(它实际上不需要我认为不需要的任何状态),并通过使用 
传递你的 props 来渲染你想要渲染的组件{...props}
,这样它就可以获取 Router 属性,但重要的是给它一个 
key
 属性,强制它从头开始重新渲染

例如,我有一些看起来像这样的东西:

<Route exact={false} path="/:customerid/:courierid/:serviceid" component={Prices} />

我希望我的组件在 URL 更改时重新呈现,但仅限于 customerid 或 serviceid 更改时。所以我把

Prices

做成了这样的功能组件:

function Prices (props) { const matchParams = props.match.params; const k = `${matchParams.customerid}-${matchParams.serviceid}`; console.log('render key (functional):'); console.log(k); return ( <RealPrices {...props} key={k} /> ) }

请注意,我的密钥仅考虑 customerid 和 serviceid - 当这两个更改时它会重新渲染,但当 courierid 更改时它不会重新渲染(如果您愿意,只需将其添加到密钥中即可)。我的

RealPrices

 组件的好处是仍然可以传递所有路线道具,例如历史记录、位置、匹配等。


2
投票
如果您正在寻找使用钩子的解决方案。

如果您要从某些 API 获取数据,那么您可以将该调用包装在

useEffect

 块内,并将 
history.location.pathname
 作为参数传递给 
useEffect

代码:

import { useHistory } from "react-router"; const App = () => { const history = useHistory(); useEffect(() => { //your api call here }, [history.location.pathname]); };
来自 
useHistory

react-router
 钩子将给出路径名称,因此每次更改 
useEffect
 时都会调用它(
url


1
投票
如@theshubhagrwl所述,但是 您可以使用 location.href 而不是 location.pathname 在所有条件下工作

import { useHistory } from "react-router"; const App = () => { const history = useHistory(); useEffect(() => { // do you task here }, [history.location.href]); };
    

0
投票
您可以使用“react-router-dom”中的 useLocation() 然后在 useEffect 依赖数组中使用该对象。

import {useLocation} from "react-router-dom"; export default function Card() { const location = useLocation(); useEffect(()=>{}, [location]); return( // your code here ); }
    

-3
投票
在 React Router v4 中,在

Switch

 标签后添加 
Router
 标签修复了问题
像这样

<Router> <Switch> </Switch> </Router>
    
© www.soinside.com 2019 - 2024. All rights reserved.