[英]React 16.4 enables getDerivedStateFromProps to be called from state change. How to cope with that?
[英]React 16.4 - manual form input fill along with its updates from getDerivedStateFromProps?
我在React 16.4上更新后遇到一個問題,其中我們使用getDerivedStateFromProps
邏輯進行了一些重大更改。 現在,它將在傳入組件和自己組件的props上的每個組件更新上觸發。
因此,我已經閱讀了文檔和手冊,但仍然無法弄清表單輸入字段應基於傳入的道具( controlled component
),並且同時能夠由用戶自己的輸入進行修改的情況?
我也嘗試過這篇文章,但是它只涉及一次性更新的情況,而不是手動輸入的情況: 為什么在setState之后調用getDerivedStateFromProps?
這是我要重現的小代碼:
import PropTypes from 'prop-types'
import React from 'react'
export class NameEditor extends React.Component {
static propTypes = {
currentLevel: PropTypes.number
}
static defaultProps = {
currentLevel: 0
}
constructor(props) {
super(props)
this.state = {
currentLevel: 0
}
}
static getDerivedStateFromProps(nextProps) {
return {
currentLevel: nextProps.currentLevel
}
}
_handleInputChange = e => {
this.setState({
currentLevel: e.target.value
})
}
render() {
const { currentLevel } = this.state
return (
<input
placeholder={0}
value={currentLevel}
onChange={this._handleInputChange}
/>
)
}
}
export default NameEditor
更新:
當前, _handleInputChange
方法將僅修改子組件的狀態,該子組件將調用getDerivedStateFromProps
。
該方法的工作方式是,它在每個newProps或setState調用發生時被調用。
因此,其行為如下:
getDerivedStateFromProps
get,它將從父組件獲取currentLevel
值,該父組件仍未進行修改,因為我們未在其中進行任何更改,因此,它將使用調用程序中存在的值覆蓋來自調用處理程序的新值。父組件,未修改。 解決此問題的方法:我們將需要一個來自父組件的回調函數,該函數的功能與handleInputChange相同。
所以:
handleCurrentLevelChange
方法,該方法將僅具有一個參數e.target.value
,其作用是在父狀態下修改currentLevel
。 handleCurrentLevelChange
傳遞給handleCurrentLevelChange
所需的名稱,可能是相同的名稱。 _handleInputChange = (e, cb) => {
this.setState({
currentLevel: e.target.value
}, () => {
cb && cb(e.target.value) //this makes the callback optional.
});
}
<input
placeholder={0}
value={currentLevel}
onChange={(e) => this._handleInputChange(e, handleCurrentLevelChange)}
onChange
屬性和處理程序的新行為將允許您的孩子和父母都進行更改。
這應該解決當前的問題。
解決方案#1(帶鍵和重新安裝):
您可能需要根據傳入的currentLevel
為其提供一個密鑰,以在每個外部props更新中重新安裝當前組件。 它看起來像:
class Wrapper ... {
...
render() {
const { currentLevel } = this.props;
return (
<NameEditor key={currentLevel} {...currentLevel} />
)
}
}
export default Wrapper
...並在組件上進行一些額外的更改,以通過告知它來阻止派生的props替換-是否是第一次渲染(因為我們計划僅通過內部重裝來控制其state
,而只能通過外部重裝來控制其state
,所以實際上是這樣) ):
import PropTypes from 'prop-types'
import React from 'react'
export class NameEditor extends React.Component {
static propTypes = {
currentLevel: PropTypes.number
}
static defaultProps = {
currentLevel: 0
}
constructor(props) {
super(props)
this.state = {
currentLevel: 0,
isFirstRender: false
}
}
static getDerivedStateFromProps(nextProps, prevProps) {
if (!prevProsp.isFirstRender) {
return {
currentLevel: nextProps.currentLevel,
isFirstRender: true
};
}
return null;
}
_handleInputChange = e => {
this.setState({
currentLevel: e.target.value
})
}
render() {
const { currentLevel } = this.state
return (
<input
placeholder={0}
value={currentLevel}
onChange={this._handleInputChange}
/>
)
}
}
export default NameEditor
因此,在這種情況下,您將有機會通過從表單手動輸入值來操縱組件狀態。
解決方案2(不按標志重新安裝) :
嘗試設置一些標志,以在每次重新渲染時將外部(getDerived ...)和內部(Controlled Comp ...)狀態更新分開。 例如,通過updateType
:
import PropTypes from 'prop-types'
import React from 'react'
export class NameEditor extends React.Component {
static propTypes = {
currentLevel: PropTypes.number
}
static defaultProps = {
currentLevel: 0
}
constructor(props) {
super(props)
this.state = {
currentLevel: 0,
updateType: 'props' // by default we expecting update by incoming props
}
}
static getDerivedStateFromProps(nextProps, prevProps) {
if (!prevState.updateType || prevState.updateType === 'props') {
return {
updateType: 'props',
currentLevel: nextProps.currentLevel,
exp: nextProps.exp
}
}
if (prevState.updateType === 'state') {
return {
updateType: '' // reset flag to allow update from incoming props
}
}
return null
}
_handleInputChange = e => {
this.setState({
currentLevel: e.target.value
})
}
render() {
const { currentLevel } = this.state
return (
<input
placeholder={0}
value={currentLevel}
onChange={this._handleInputChange}
/>
)
}
}
export default NameEditor
PS這可能是一種反模式(希望Dan永遠不會看到這一點),但現在我無法找到更好的解決方案。
解決方案#3 :
請參閱Sultan H.下一篇文章,關於具有包裝器組件顯式回調的受控邏輯。
因為在設置狀態之后,React會調用渲染,但是在渲染之前,您總是會調用getDerivedStateFromProps
方法。
setState計划對組件狀態對象的更新。 狀態改變時,組件通過重新渲染做出響應
在初始安裝和后續更新上,都在調用render
方法之前立即調用getDerivedStateFromProps。 它應該返回一個對象以更新狀態,或者返回null則不更新任何內容。
https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.