Why
在React 16.3版本中,React官方推出了新的生命週期方法,而有一部分舊的生命週期方法則被標記為Unsafe
,該方法在React17中將會被廢棄,而今日的主角componentWillReceiveProps
則是其中一個。
componentWillReceiveProps
先來看看componentWillReceiveProps
是怎麼用的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| import * as React from "react"; import * as ReactDOM from "react-dom";
interface IInputProps { value?: string; defaultValue?: string; onChange?: (value: string) => void; }
interface IInputState { value: string; }
class Input extends React.Component<IInputProps, IInputState> { public constructor(props: IInputProps) { super(props);
const initialValue = props.value ? props.value : props.defaultValue ? props.defaultValue : "";
this.state = { value: initialValue }; }
public UNSAFE_componentWillReceiveProps(nextProps: IInputProps) { if (nextProps.value !== undefined && nextProps.value !== this.props.value) { this.setState({ value: nextProps.value }); } }
handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { const { onChange } = this.props; if (onChange) { onChange(e.target.value); } else { this.setState({ value: e.target.value }); } };
public render(): React.ReactNode { const { value } = this.state; return <input value={value} onChange={this.handleChange} />; } }
const App = () => { const [value, setValue] = React.useState(); return ( <> <Input value={value} onChange={value => { setValue(value); }} /> </> ); };
ReactDOM.render(<App />, document.getElementById("root"));
|
getDerivedStateFromProps
getDerivedStateFromProps
和componentWilLReceiveProps
最大的不同就是前者靜態(static),後者是類方法,也就是getDerivedStateFromProps
不能訪問this。第二個不同是調用的次數和時機。
看看這個React15版本的生命週期圖。
再看看這個React16版本比較比較。
在React15中,componentWilLReceiveProps
只會在更新(Updating)的時候調用,而React16的getDerivedStateFromProps
在掛載(Mounting)和更新(Updating)時都會調用,因此轉換要需要注意添加處理掛載時的邏輯。
開始轉換
可以看到在掛載時, componentWilLReceiveProps
並沒有被調用,在輸入的時候(Input的input -> handleChange -> props.onChange -> App的setValue -> App的value改變 -> Input更新),componentWillReceiveProps
被調用一次。
把componentWilLReceiveProps
替換為getDerivedStateFromProps
。
1 2 3 4 5 6 7 8 9 10 11 12
| static getDerivedStateFromProps( nextProps: IInputProps, prevState: IInputState ) { if (nextProps.value !== undefined && nextProps.value !== prevState.value) { return { value: nextProps.value }; } else { return null; } }
|
在第一次掛載的時候,getDerivedStateFromProps
就已經被調用了一次,這時prevState就是construtor裡設置的。
在替換成getDerivedStateFromProps
的時候,需要注意週用時機和次數即可。