React - 使用React-Router LINK标记会导致父级重新呈现

时间:2016-02-24 20:26:31

标签: hyperlink reactjs duplicates components render

在这里反应新手。我很难过。我有一个主类,有一个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中的任何链接时,通过Route,它会加载Topic并向其传递正确的主题ID。然后,Topic中的componentWillReceiveProps调用商店,该商店下载该主题的帖子列表。一切正常。路由器非常简单:

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

问题:出于某种原因,除了我的构思之外,每次点击标题中的链接时都会重新呈现 Main。这会导致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

在主题的初始渲染之后,主要调用再次渲染!这导致主题加载两次,并且两次调用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标签在单击时会使其父组件重新渲染!我敢肯定我一定做错了什么 - 但是什么?感谢您提供的任何见解/帮助!

1 个答案:

答案 0 :(得分:0)

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

当路径匹配时路由呈现,唯一不会重新呈现的是你写的shouldComponentUpdate在不应该重新渲染的条件下返回false - 但是不要用它来解决你当前的问题。

而不是在componentWillReceiveProps中提取数据,而不是componentWillMount