React Router v4中component和render的区别

前端之家收集整理的这篇文章主要介绍了React Router v4中component和render的区别前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

昨日在一个使用了React Router的项目中发现一个问题,一个组件一直渲染不出来,排查了一个下午才定位到问题所在。为了简化问题,demo代码如下

class Index extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <BrowserRouter>
          <Route path="/" component={Home}/>
        </BrowserRouter>
      </Provider>
    )
  }
}

class Home extends React.Component {
  handle = () => {
    return (<WrappedTest/>);
  }

  render() {
    return (
      <div>
        <Route path="/home" render={this.handle}/>
      </div>
    )
  }
}

class Test extends React.Component {
  componentWillMount() {
    console.log('Test componentWillMount');
  }

  render() {
    return (
      <div>
        <Link to="/home/test">show</Link>
        <Route path="/home/test" render={() => <h3>hi</h3>}/>
      </div>
    )
  }
}

const WrappedTest = connect()(Test);

ReactDOM.render(<Index/>,document.getElementById('root'));

入口url是"/home",初次进入页面时Test组件就已经被挂载了,上面有一个show按钮,期望效果是点击按钮时跳到"/home/test",而这个路由会显示"hi"字符串。

可是实际点击后发现地址是跳转了,但是字符串没有显示出来,排查后发现是Test的render没有被调用

这个问题由两个因素引起,第一个是因为redux的connect函数包装过的组件默认会有一个优化,第二个是因为react-router中的内联渲染方式,当这两者一起出现时就可能会出现这样的问题。

对于第一个原因,connect在包装组件时会对组件的shouldComponentUpdate方法有一个默认的实现,也就是对组件的props进行一个浅比较,如果props没有变化则不会调用render方法,比如上面的例子中只是点击了link,而没有改变任何prop,所以render方法没有被触发。

第二个原因,在react-router v4中,有两种常见的渲染组件的方式:component和render。前者是使用React.createElement方法新建一个元素,而后者仅仅是调用现有组件的render方法

所以对于上面的例子来说,有两种方式可以解决,第一种是在connect时关闭这种优化

const WrappedTest = connect(null,null,{pure: false})(Test);
注意第4个参数,pure设置为false即可。表示不进行浅对比,让shouldComponentUpdate总是返回true从而触发渲染。
第二种办法是在route中使用component而不是render。
<Route path="/home" component={WrappedTest}/>

参考资料:

https://reacttraining.cn/web/api/Route/component

https://leozdgao.me/reacthe-reduxde-qiao-jie-react-redux

原文链接:https://www.f2er.com/react/303377.html

猜你在找的React相关文章