You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// AfterclassExampleComponentextendsReact.Component{// Initialize state in constructor,// Or with a property initializer.state={isScrollingDown: false,lastRow: null,};staticgetDerivedStateFromProps(props,state){if(props.currentRow!==state.lastRow){return{isScrollingDown: props.currentRow>state.lastRow,lastRow: props.currentRow,};}// Return null to indicate no change to state.returnnull;}}
你可能想知道为什么我们不简单地将先前的 props 作为参数传递给 getDerivedStateFromProps。我们在设计 API 时考虑过这个问题,但因为两点原因推翻这个想法:
classScrollingListextendsReact.Component{listRef=null;previousScrollOffset=null;componentWillUpdate(nextProps,nextState){// Are we adding new items to the list?// Capture the scroll position so we can adjust scroll later.if(this.props.list.length<nextProps.list.length){this.previousScrollOffset=this.listRef.scrollHeight-this.listRef.scrollTop;}}componentDidUpdate(prevProps,prevState){// If previousScrollOffset is set, we've just added new items.// Adjust scroll so these new items don't push the old ones out of view.if(this.previousScrollOffset!==null){this.listRef.scrollTop=this.listRef.scrollHeight-this.previousScrollOffset;this.previousScrollOffset=null;}}render(){return(<divref={this.setListRef}>{/* ...contents... */}</div>);}setListRef=ref=>{this.listRef=ref;jsx};}
在上面的示例中, 在 componentWillUpdate 中读取 DOM 属性。但是在异步渲染中,这可能被延迟到 “render” 阶段(像 componentWillUpdate and render)和 “commit” 阶段(像 componentDidUpdate)才执行。如果用户在这期间做了一些类似调整窗口大小,从 componentWillUpdate 中读取的 scrollHeight 值会是旧的。
这个问题的解决方案就是使用新的 “commit” 阶段的生命周期事件,getSnapshotBeforeUpdate。这个方当会在变更产生后立即被调用(比如在 DOM 被更新之前)。它可以返回一个值并作为参数传到 componentDidUpdate。
classScrollingListextendsReact.Component{listRef=null;getSnapshotBeforeUpdate(prevProps,prevState){// Are we adding new items to the list?// Capture the scroll position so we can adjust scroll later.if(prevProps.list.length<this.props.list.length){return(this.listRef.scrollHeight-this.listRef.scrollTop);}returnnull;}componentDidUpdate(prevProps,prevState,snapshot){// If we have a snapshot value, we've just added new items.// Adjust scroll so these new items don't push the old ones out of view.// (snapshot here is the value returned from getSnapshotBeforeUpdate)if(snapshot!==null){this.listRef.scrollTop=this.listRef.scrollHeight-snapshot;}}render(){return(<divref={this.setListRef}>{/* ...contents... */}</div>);}setListRef=ref=>{this.listRef=ref;};}
React 组件的生命周期
Before React 16.3
After React 16.3
After React 16.4
React 声明周期可能会经历如下三个过程:
装配过程
constructor
构造函数是初始化状态的合适位置。若你不初始化状态且不绑定方法,那你也不需要为你的React组件定义一个构造函数。
static getDerivedStateFromProps
组件实例化后和接受新属性时将会调用
getDerivedStateFromProps
UNSAFE_componentWillMount
在装配发生前被立刻调用。其在
render()
之前被调用,因此在这方法里同步地设置状态将不会触发重渲。这是唯一的会在服务端渲染调起的生命周期钩子函数。
render
render()
函数应该纯净,它不应该改变组件的状态,其每次调用都应返回相同的结果。保持render()
方法纯净使得组件更容易思考。componentDidMount
在组件被装配后立即调用。初始化使得DOM节点应该进行到这里。若你需要从远端加载数据,这是一个适合实现网络请求的地方。在该方法里设置状态将会触发重渲。
更新过程
UNSAFE_componentWillReceiveProps
在装配了的组件接收到新属性前调用。
只要是父组件的 render 函数被调用,在 render 函数中的子组件就会经历更新过程,不管传给子组件的 props 有没有改变,都会触发子组件的
componentWillReceiveProps
函数。static getDerivedStateFromProps
你可能想知道为什么我们不简单地将先前的 props 作为参数传递给
getDerivedStateFromProps
。我们在设计 API 时考虑过这个问题,但因为两点原因推翻这个想法:prevProps
参数在第一次调用getDerivedStateFromProps
(实例化后) 时会是 null。 需要在每次访问prevProps
时判断 if-not-null。shouldComponentUpdate
让React知道当前状态或属性的改变是否不影响组件的输出。
UNSAFE_componentWillUpdate
当接收到新属性或状态时,
UNSAFE_componentWillUpdate()
为在渲染前被立即调用。render
getSnapshotBeforeUpdate
在最新的渲染输出提交给DOM前将会立即调用。它让你的组件能在当前的值可能要改变前获得它们。
在上面的示例中, 在
componentWillUpdate
中读取 DOM 属性。但是在异步渲染中,这可能被延迟到 “render” 阶段(像componentWillUpdate
andrender
)和 “commit” 阶段(像componentDidUpdate
)才执行。如果用户在这期间做了一些类似调整窗口大小,从componentWillUpdate
中读取的scrollHeight
值会是旧的。这个问题的解决方案就是使用新的 “commit” 阶段的生命周期事件,
getSnapshotBeforeUpdate
。这个方当会在变更产生后立即被调用(比如在 DOM 被更新之前)。它可以返回一个值并作为参数传到componentDidUpdate
。componentDidUpdate
会在更新发生后立即被调用。该方法并不会在初始化渲染时调用。
卸载过程
componentWillUnmount
在组件被卸载和销毁之前立刻调用。可以在该方法里处理任何必要的清理工作,例如解绑定时器,取消网络请求,清理任何在
componentDidMount
环节创建的DOM元素。参考资料:
React.Component
React v16.3.0: New lifecycles and context API
The text was updated successfully, but these errors were encountered: