【问题标题】:How to re-render a component with React-Router <Link> pointing to the same URL如何使用指向相同 URL 的 React-Router <Link> 重新渲染组件
【发布时间】:2020-02-26 14:56:43
【问题描述】:

为简单起见,详细信息页面根据 URL 中的电影 ID 获取装载数据,这来自路径中的 path='movie/:id'。

它的孩子被称为推荐,它再次根据当前 URL 向您显示推荐的电影。

class MovieDetailPage extends React.Component {

    // Fetch movies and cast based on the ID in the url
    componentDidMount() {
        this.props.getMovieDetails(this.props.match.params.id)
        this.props.getMovieCast(this.props.match.params.id)
    }



    render() {            
        <div>
          Movies here
        </div>
        <Recommended id={this.props.match.params.id}/>
    }
}

Recommended 组件也会根据当前电影获取数据,并生成另一个指向另一部电影的标签。

class Recommended extends React.Component {

    componentDidMount() {
        this.props.getRecommended(this.props.id)
    }

    render() {
        return (
            <>
            <Category title={'Recommended'}></Category>
            <div className="movies">
                {   
                    this.props.recommended.map((movie) => {
                        return (
                            <Link key={movie.id} to={`movie/${movie.id}`} className="movies__item">
                                <img
                                    key={movie.id}
                                    src={`https://image.tmdb.org/t/p/w342${movie.poster_path}`} 
                                    className="movies__item-img"
                                    alt={`A poster of ${movie.title}`}
                                >
                                </img>
                            </Link>
                        )                      
                    })
                }
            </div>
            </>
        )
    }
}

现在如何在点击推荐组件中生成的链接时触发父组件的另一个渲染? URL 正在更改,但这不会像我打算那样触发渲染。

更新:

<Route 
  path="/movie/:id" 
  render={(props) => (
  <MovieDetailPage key={props.match.params.id} 
  {...props} 
  )}
/>

这次我传入了一个触发页面重新呈现的唯一键。我以前试过这个,但我可能搞砸了语法。

这篇文章让我找到了正确的方向:Force remount component when click on the same react router Link multiple times

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    向页面添加一个键

    如果您更改路线但您的页面没有获得其“装载”数据,那么您应该向页面添加一个键。这将导致您的页面重新渲染并使用新 id 挂载并再次获取数据。

    你可以阅读更多关于反应键here

    一个键告诉 react 这是一个特定的组件,这就是你在列表中看到它们的原因。通过更改页面上的键,您告诉 react 这是组件的新实例并且已更改。这将导致重新安装。

    类组件示例

    class MyPage extends React.Component {
        componentDidMound() {
          // this will fire each time the key changes since it triggers a mount
        }
    
        render() {
            return (
                <div key={props.pageId}>
                   {/* component stuff */} 
                </div>
            )
        }
    }
    

    功能组件示例

    const MyPage = (props) => {
        React.useEffect(() => {
          // this will fire each time the key changes
        }, []);
    
        return (
            <div key={props.pageId}>
               {/* component stuff */} 
            </div>
        )
    }
    

    【讨论】:

    • 你能扩展一下吗?我不确定如何向 MovieDetail 组件添加密钥。我是否像这样通过 Route 传递此密钥: 或其他地方?我可以通过传递一个键来重新呈现推荐组件,但我的目的是让父级在单击子级中生成的链接时再次呈现。
    • 页面组件的 props 中应该有一些细节。其中之一将是 url 或至少是 :id。使用它也可以将键添加到顶级组件。
    • 请原谅我的无知,我对 React 还是很陌生,但我认为你不能将道具从 Child 传递给 Parent 组件?我猜我的应用程序中的顶级组件是一个类组件,它有 BrowserRouter 和里面的所有路由。我确实可以访问新路径,但我不知道如何“向上”传递该道具并基于该道具创建密钥。目前它“起作用”的唯一方法是我手动刷新页面,因为我的 URL 在单击电影时会发生变化,因此在刷新和安装时会相应地进行绘制。
    • 没关系!再次回到它并尝试做基本相同的事情,这一次它就像一个魅力!我更新了我的帖子。感谢您的帮助。
    • 嘿干得好!这正是我的意思。对不起,如果我没有解释清楚。
    【解决方案2】:

    您可以在您的推荐组件中添加另一个 React 生命周期方法,该方法在接收新道具时触发(UNSAFE_componentWillReceiveProps、componentDidUpdate、getDerivedStateFromProps),如下所示:

    UNSAFE_componentWillReceiveProps(nextProps) {
      if (nextProps.id !== this.props.id) {
        nextProps.getRecommended(nextProps.id);
      };
    }
    

    您还可以向组件添加密钥(如果密钥更改,这会强制它完全重新渲染),如下所示:

    &lt;Recommended key={this.props.match.params.id} id={this.props.match.params.id}/&gt;

    您还可以使用 React Hooks 来通过 useEffect 更轻松地处理这个问题:

    const Recommended = (props) => {
      const { id, getRecommended, recommended } = props;
      useEffect(() => {
        id && getRecommended(id);
      }, [id]);
    
      return (
        <>
          <Category title={'Recommended'}></Category>
          <div className="movies">
            {recommended.map((movie) => {
              return (
                <Link key={movie.id} to={`movie/${movie.id}`} className="movies__item">
                  <img
                    key={movie.id}
                    src={`https://image.tmdb.org/t/p/w342${movie.poster_path}`}
                    className="movies__item-img"
                    alt={`A poster of ${movie.title}`}
                  ></img>
                </Link>
              );
            })}
          </div>
        </>
      );
    };
    

    注意:向组件添加密钥并完成其重新渲染不是最佳做法,您应该尽可能使用组件的生命周期来避免它

    【讨论】:

      猜你喜欢
      • 2021-12-15
      • 2017-05-17
      • 2020-11-19
      • 2022-07-20
      • 1970-01-01
      • 2018-05-25
      • 2016-03-19
      • 2016-06-07
      • 1970-01-01
      相关资源
      最近更新 更多