【问题标题】:React - using React-Router LINK tag causes parent to re-renderReact - 使用 React-Router LINK 标签会导致父级重新渲染
【发布时间】:2016-06-07 08:19:01
【问题描述】:

在这里反应新手。我难住了。我有一个主类,它有一个 Header 区域和一个 Body 区域。 Header 区域具有用于下载不同类别 JSON 的导航链接。在启动时,一个随机的帖子被插入到正文中:

var React = require('react');
var Header = require('./header');
var PostRandom = require('./post-random');

module.exports = React.createClass({
    render: function(){
        console.log("MAIN.render");
        return <div>
            <Header />
            {this.content()}

        </div>
    },
    content: function(){
        console.log("MAIN.content");
        if(this.props.children){
            return this.props.children
        }else{
            return <PostRandom />
        }
    }
}); 

这是标题:

var React = require('react');
var Router = require ('react-router');
var Link = Router.Link;
var categories = {
    cats: [{
        name: 'Writing',
        id: 10
      },
      {
        name: 'Essays',
        id: 15
      },
      {
        name: 'Poetry',
        id: 23
      }
      ]
  };

module.exports = React.createClass({
    getInitialState: function(){
        console.log("HEADER.getInitialState")
        return {
            topics: categories.cats,
        }
    },
    render: function(){
        console.log("HEADER.RENDER");
        return <nav className="navbar navbar-static-top">
                <div className="container-fluid">
                    <IndexLink to="/" className = "navbar-brand">
                        Home
                    </IndexLink>
                    <ul className = "nav navbar-nav navbar-right">
                        {this.renderTopics()}
                    </ul>
                </div>
            </nav>
    },
    renderTopics: function(){
        console.log("HEADER: renderTopics")
        return this.state.topics.slice(0,8).map(function(topic){
            return <li >
                <Link activeClassName="active" to={"topics/" + topic.id}>
                    {topic.name}
                </Link>
            </li>
        });
    }
});

当我通过路由单击 Header 中的任何链接时,它会加载主题并将正确的主题 ID 传递给它。然后 Topic 中的 componentWillReceiveProps 调用商店,该商店下载该主题的帖子列表。这一切都很好。路由器非常简单:

<Route  path="/" component = {Main}>
     <Route path="topics/:id"  component = {Topic} />
</Route>

问题:出于某种超出我想象的原因,每次单击标题中的链接时都会重新渲染主页面。这会导致 Header 重新渲染,从而使 Topic 重新渲染,从而导致对 Store 的第二次调用。我不明白。控制台输出如下所示:

MAIN.render
MAIN.content
HEADER.RENDER
HEADER: renderTopics
TOPIC: componentWillReceiveProps
TOPIC: render
TOPIC:renderPosts
MAIN.render
MAIN.content
HEADER.RENDER
HEADER: renderTopics
TOPIC: componentWillReceiveProps
TOPIC: render
TOPIC:renderPosts
STORE: triggerChange
TOPIC:onChange
TOPIC: render
TOPIC:renderPosts
STORE: triggerChange
TOPIC:onChange
TOPIC: render
TOPIC:renderPosts

Topic 初始渲染后,Main 调用再次渲染!这导致主题被加载两次,并且两次调用 componentWillReceiveProps,因此两次到商店。我最终下载了两次 JSON,并获得了两个不同的随机帖子数组。我看到了一个随机帖子的初始列表,然后将其替换为第二个随机帖子列表。呃。

如果我重新加载页面,停留在同一个主题,Main 不会被第二次调用 - 所以点击链接会导致重新渲染。这是重新加载的控制台输出:

MAIN.render
MAIN.content
HEADER.getInitialState
HEADER.RENDER
HEADER: renderTopics
TOPIC: getInitialState
TOPIC: componentWillMount
TOPIC: render
TOPIC:renderPosts
58 STORE: triggerChange
TOPIC:onChange
TOPIC: render
TOPIC:renderPosts

也很有趣:如果我将 Link 标签更改为只返回主页 - 也就是说,根本不调用/呈现主题 - 就像这样:

<Link activeClassName="active" to={"/"}>

Main 仍然会重新渲染,这会重新渲染 Header!控制台输出:

MAIN.render
MAIN.content
HEADER.RENDER
HEADER: renderTopics

所以它与 Topic 中发生的事情或对 Store 的调用无关 - 当单击 Link 标签时,它的父组件会重新渲染!我确定我一定做错了什么——但是什么?感谢您提供的任何见解/帮助!

【问题讨论】:

  • 我也遇到了同样的问题,点击内部链接时,父级的render方法被一次又一次调用

标签: hyperlink reactjs duplicates components render


【解决方案1】:

渲染不应触发副作用。如果您发现自己试图控制何时调用 render,那么您就走错了路。

路由在其路径匹配时渲染,唯一不会重新渲染的情况是,如果您编写了 shouldComponentUpdate,它在不应该重新渲染的情况下返回 false ——但不要用它来解决您当前的问题问题。

不是在componentWillReceiveProps 中获取数据,而是应该在componentWillMount 中获取数据。

【讨论】:

  • 1.当调用 render 时,我并没有试图“控制”——它在那儿被调用是没有意义的。 2. 我必须使用 componentWillReceiveProps,因为当用户点击主题链接时,组件会使用新的 JSON 进行更新。好消息:我(不经意间)(大部分)通过解决另一个问题解决了这个问题 - 消除“垃圾”网址。我向路由器添加了一个历史参数(以摆脱“垃圾”网址)并且不再获得双重渲染! (加上我的网址看起来不错......)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-27
  • 1970-01-01
  • 2017-03-06
  • 2020-11-21
  • 2016-04-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多