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 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |