路由参数更改时组件不会重新安装

IT技术 reactjs react-router
2021-04-11 00:22:16

我正在使用 react-router 开发一个 react 应用程序。我有一个项目页面,其网址如下:

myapplication.com/project/unique-project-id

当项目组件加载时,我会从 componentDidMount 事件触发该项目的数据请求。我现在遇到了一个问题,如果我直接在两个项目之间切换,那么只有 id 像这样改变......

myapplication.com/project/982378632
myapplication.com/project/782387223
myapplication.com/project/198731289

componentDidMount 不会再次触发,因此不会刷新数据。是否应该使用另一个生命周期事件来触发我的数据请求或解决此问题的不同策略?

6个回答

如果您确实需要在路由更改时重新安装组件,您可以将唯一键传递给组件的键属性(键与您的路径/路由相关联)。所以每次路由改变时,key 也会改变,触发 React 组件卸载/重新挂载。我从这个答案中得到了想法

但这不是一个巨大的影响?你有什么建议我们可以安全地使用它而不会有太大的影响吗?
2021-05-30 00:22:16
杰出的!谢谢你这个简单而优雅的回答
2021-06-06 00:22:16
@AlpitAnand 您的问题太宽泛且特定于应用程序。对于某些应用程序,是的,这会影响性能,在这种情况下,您应该自己观察 props 的变化并只更新应该更新的元素。对于大多数人来说,以上是一个很好的解决方案
2021-06-07 00:22:16
@AlpitAnand 这是一个广泛的问题。重新安装肯定比重新渲染慢,因为它会触发更多的生命周期方法。在这里,我只是回答如何在路线更改时进行重新挂载。
2021-06-19 00:22:16
只是问一下,这不会影响应用程序的性能吗?
2021-06-20 00:22:16

这是我的答案,类似于上面的一些但有代码。

<Route path="/page/:pageid" render={(props) => (
  <Page key={props.match.params.pageid} {...props} />)
} />
这是一个很好的答案 - 让我免于 componentDidUpdate 地狱;)
2021-05-28 00:22:16
这里的关键起着最大的作用,因为你在个人资料页面中有链接到的图像,点击它只是重定向到相同的路由,但具有不同的参数,但组件不会更新,因为 React 找不到差异,因为必须有一个KEY来比较旧的结果
2021-05-30 00:22:16
最好的答案,因为只有在更改 :pageid 参数时才更新 comp。
2021-05-30 00:22:16

如果链接指向相同的路由,只是使用不同的参数,则不会重新安装,而是接收新的props。因此,您可以使用该componentWillReceiveProps(newProps)函数并查找newProps.params.projectId.

如果您尝试加载数据,我建议您在路由器使用组件上的静态方法处理匹配之前获取数据。看看这个例子。react-router巨型演示这样,组件将加载数据并在路由参数更改时自动更新,而无需依赖componentWillReceiveProps.

仅供参考:“componentWillReceiveProps”被视为遗留
2021-05-25 00:22:16
谢谢你。我能够使用 componentWillReceiveProps 来完成这项工作。我还是不太了解 React Router Mega Demo 数据流。我看到在某些组件上定义了静态 fetchData。这些静态是如何从路由器客户端调用的?
2021-05-28 00:22:16
这可行,但有一个问题,您需要添加 componentWillReceiveProps() 或 componentDidUpdate() 来处理对每个加载数据的组件的重新渲染。例如,考虑一个页面,它有多个基于相同路径参数加载数据的组件。
2021-06-05 00:22:16
很好的问题。查看 client.js 文件和 server.js 文件。在路由器的运行周期中,它们调用 fetchData.js 文件并将 传递state给它。一开始有点混乱,但后来变得更清晰了。
2021-06-11 00:22:16
你应该在 React 16 中使用 ComponentDidUpdate 因为 componentWillReceiveProps 已被弃用
2021-06-17 00:22:16

您必须清楚,路由更改不会导致页面刷新,您必须自己处理。

import theThingsYouNeed from './whereYouFindThem'

export default class Project extends React.Component {

    componentWillMount() {

        this.state = {
            id: this.props.router.params.id
        }

        // fire action to update redux project store
        this.props.dispatch(fetchProject(this.props.router.params.id))
    }

    componentDidUpdate(prevProps, prevState) {
         /**
         * this is the initial render
         * without a previous prop change
         */
        if(prevProps == undefined) {
            return false
        }

        /**
         * new Project in town ?
         */
        if (this.state.id != this.props.router.params.id) {
           this.props.dispatch(fetchProject(this.props.router.params.id))
           this.setState({id: this.props.router.params.id})
        }

    }

    render() { <Project .../> }
}
是的,这实际上不是最佳实践,抱歉,在发送“fetchProject”之后,您的减速器无论如何都会更新您的道具,我只是用它来表达我的观点,而没有将 redux 放到位
2021-05-29 00:22:16
嗨,chickenchilli,我实际上还停留在这个问题上……你有其他建议或推荐教程吗?或者我现在会坚持你的解决方案。谢谢你的帮助!
2021-05-30 00:22:16
谢谢,这个解决方案对我有用。但是我的 eslint 设置在抱怨这个:github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/...你怎么看这个?
2021-06-12 00:22:16

如果你有:

<Route
   render={(props) => <Component {...props} />}
   path="/project/:projectId/"
/>

在 React 16.8 及更高版本中,使用 hooks,您可以:

import React, { useEffect } from "react";
const Component = (props) => {
  useEffect(() => {
    props.fetchResource();
  }, [props.match.params.projectId]);

  return (<div>Layout</div>);
}
export default Component;

在那里,您只会fetchResourceprops.match.params.id发生变化触发新呼叫

这是更好的答案,因为大多数其他答案都依赖于现在已弃用且不安全的 componentWillReceiveProps
2021-05-22 00:22:16