React组件未接收新props:点击按钮后componentWillReceiveProps未触发
问题分析与解决方案
嘿,这个问题的核心是你没摸透React的状态/更新触发逻辑,咱们一步步拆解:
为什么componentWillReceiveProps没被调用?
你定义的isLoading是个普通的全局变量,当点击按钮修改它的值时,React完全不知道这个变量发生了变化——React的组件更新只有两种触发途径:
- 组件自身的状态(
setState)发生改变 - 父组件重新渲染,导致当前组件的
props更新
而你的代码里,ReactDOM.render只执行了一次:第一次渲染时把isLoading=false传给了<App />。之后哪怕isLoading变成true,因为没有触发重新渲染,<App />接收到的props还是最初的false,自然不会触发componentWillReceiveProps。
怎么解决这个问题?
这里有两种符合React设计思路的方案:
方案一:把isLoading改成React状态(推荐)
把isLoading放到父组件的状态里,这样修改状态时会自动触发重新渲染,<App />就能拿到更新后的props:
class Parent extends React.Component { constructor(props) { super(props); this.state = { isLoading: false }; this.request = this.request.bind(this); } request() { // 修改状态,触发父组件重新渲染 this.setState({ isLoading: true }); } render() { // 每次渲染都会把最新的isLoading传给App return <App isLoading={this.state.isLoading} request={this.request} />; } } ReactDOM.render(<Parent />, document.querySelector("#app"));
这样点击按钮后,request会调用setState更新父组件状态,父组件重新渲染时把新的isLoading传给<App />,componentWillReceiveProps就会被正常触发了。
方案二:手动触发重新渲染(不推荐)
如果一定要用全局变量,那修改isLoading后手动调用ReactDOM.render重新渲染组件:
let isLoading = false; const request = function() { isLoading = true; // 手动重新渲染,传入更新后的isLoading ReactDOM.render( <App isLoading={isLoading} request={request} />, document.querySelector("#app") ); }; ReactDOM.render( <App isLoading={isLoading} request={request} />, document.querySelector("#app") );
不过这种方式违背了React“状态驱动UI”的设计理念,代码维护性差,只适合临时测试用。
额外小提示
你用的componentWillReceiveProps在React 16.3版本之后已经被标记为过时(legacy)API了,官方推荐使用static getDerivedStateFromProps来替代它处理props更新的逻辑哦~
内容的提问来源于stack exchange,提问作者hh54188
相关产品推荐
相关产品推荐

