// Before
class ExampleComponent extends React.Component {
componentWillReceiveProps(nextProps) {
if (this.props.isVisible !== nextProps.isVisible) {
logVisibleChange(nextProps.isVisible);
}
}
}
// After
class ExampleComponent extends React.Component {
componentDidUpdate(prevProps, prevState) {
if (this.props.isVisible !== prevProps.isVisible) {
logVisibleChange(this.props.isVisible);
}
}
}
6. props更改时获取外部数据
// Before
componentWillReceiveProps(nextProps) {
if (nextProps.id !== this.props.id) {
this.setState({externalData: null});
this._loadAsyncData(nextProps.id);
}
}
// After
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.id !== prevState.prevId) {
return {
externalData: null,
prevId: nextProps.id,
};
}
return null;
}
componentDidUpdate(prevProps, prevState) {
if (this.state.externalData === null) {
this._loadAsyncData(this.props.id);
}
}
7. 在更新之前, 读取 DOM
**componentWillUpdate用于读取DOM属性。然而,对于异步渲染,“渲染”阶段生命周期(如componentWillUpdate和render)与“提交”阶段生命周期(如componentDidUpdate)之间可能会出现延迟。如果用户在这段时间内做了类似调整窗口大小的操作,则scrollHeight读取的值componentWillUpdate将会过时。
解决这个问题的方法是使用新的“提交”阶段生命周期getSnapshotBeforeUpdate。在进行改变之前立即调用此方法(例如,在更新DOM之前)。它可以返回一个值作为参数传递给React,在其改变后立即componentDidUpdate调用它。**
// Before
class ScrollingList extends React.Component {
listRef = null;
previousScrollHeight = null;
componentWillUpdate(nextProps, nextState) {
// Are we adding new items to the list?
// Capture the current height of the list so we can adjust scroll later.
if (this.props.list.length < nextProps.list.length) {
this.previousScrollHeight = this.listRef.scrollHeight;
}
}
componentDidUpdate(prevProps, prevState) {
// If previousScrollHeight 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.previousScrollHeight !== null) {
this.listRef.scrollTop +=
this.listRef.scrollHeight -
this.previousScrollHeight;
this.previousScrollHeight = null;
}
}
render() {
return (
{/* ...contents... */}
);
}
setListRef = ref => {
this.listRef = ref;
};
}
// After
class ScrollingList extends React.Component {
listRef = null;
getSnapshotBeforeUpdate(prevProps, prevState) {
// Are we adding new items to the list?
// Capture the current height of the list so we can adjust scroll later.
if (prevProps.list.length < this.props.list.length) {
return this.listRef.scrollHeight;
}
return null;
}
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;
}
}
React V_16.3.0
1.即将淘汰的API.
2.新增API
componentDidUpdate()
该生命周期不经常需要用到的,但可用于在恢复期间手动保存滚动位置的情况。 与此同时这个新的生命周期功能涵盖componentWillUpdate。getDerivedStateFromProps(nextProps, prevState)
state的更新基于props 该静态生命周期在组件实例化以及接收新 Props 后调用。 它可以 返回要更新的对象state,或是使用 null 指示新的 props, 让 state 不需要更新。getSnapshotBeforeUpdate(prevProps, prevState)
该新的 生命周期在进行突变之前被调用(例如,在DOM被更新之前)。 此生命周期的返回值将作为第三个参数传递给componentDidUpdate。3. Example
初始化, 与之前不一, 弃用 componentWillMount , 直接初始化即可
// After class ExampleComponent extends React.Component { state = { currentColor: this.props.defaultColor, palette: 'rgb', } }
// Before componentWillMount() { this._asyncRequest = asyncLoadData().then( externalData => { this._asyncRequest = null; this.setState({externalData}); } ); }
// After componentDidMount() { this._asyncRequest = asyncLoadData().then( externalData => { this._asyncRequest = null; this.setState({externalData}); } ); }
// Before // componentWillReceiveProps生命周期往往是误用在这方面做存在的问题。因此,该方法将被弃用。 componentWillReceiveProps(nextProps) { if (this.props.currentRow !== nextProps.currentRow) { this.setState({ isScrollingDown: nextProps.currentRow > this.props.currentRow, }); } } // After static getDerivedStateFromProps(nextProps, prevState) { if (nextProps.currentRow !== prevState.lastRow) { return { isScrollingDown: nextProps.currentRow > prevState.lastRow, lastRow: nextProps.currentRow, }; }
// Before class ExampleComponent extends React.Component { componentWillUpdate(nextProps, nextState) { if ( this.state.someStatefulValue !== nextState.someStatefulValue ) { nextProps.onChange(nextState.someStatefulValue); } } } // After class ExampleComponent extends React.Component { componentDidUpdate(prevProps, prevState) { if ( this.state.someStatefulValue !== prevState.someStatefulValue ) { this.props.onChange(this.state.someStatefulValue); } } }
// Before class ExampleComponent extends React.Component { componentWillReceiveProps(nextProps) { if (this.props.isVisible !== nextProps.isVisible) { logVisibleChange(nextProps.isVisible); } } } // After class ExampleComponent extends React.Component { componentDidUpdate(prevProps, prevState) { if (this.props.isVisible !== prevProps.isVisible) { logVisibleChange(this.props.isVisible); } } }
// Before componentWillReceiveProps(nextProps) { if (nextProps.id !== this.props.id) { this.setState({externalData: null}); this._loadAsyncData(nextProps.id); } } // After static getDerivedStateFromProps(nextProps, prevState) { if (nextProps.id !== prevState.prevId) { return { externalData: null, prevId: nextProps.id, }; } return null; } componentDidUpdate(prevProps, prevState) { if (this.state.externalData === null) { this._loadAsyncData(this.props.id); } }
// Before class ScrollingList extends React.Component { listRef = null; previousScrollHeight = null;
componentWillUpdate(nextProps, nextState) { // Are we adding new items to the list? // Capture the current height of the list so we can adjust scroll later. if (this.props.list.length < nextProps.list.length) { this.previousScrollHeight = this.listRef.scrollHeight; } }
componentDidUpdate(prevProps, prevState) { // If previousScrollHeight 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.previousScrollHeight !== null) { this.listRef.scrollTop += this.listRef.scrollHeight - this.previousScrollHeight; this.previousScrollHeight = null; } }
render() { return (
}
setListRef = ref => { this.listRef = ref; }; }
// After class ScrollingList extends React.Component { listRef = null;
getSnapshotBeforeUpdate(prevProps, prevState) { // Are we adding new items to the list? // Capture the current height of the list so we can adjust scroll later. if (prevProps.list.length < this.props.list.length) { return this.listRef.scrollHeight; } return null; }
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 (
}
setListRef = ref => { this.listRef = ref; }; }