我正在学习reactjs,我用componentWillReceiveProps(cWRP)方法编写了component,但是我读到它已被弃用,必须替换为getDerivedStateFromProps(gDSFP)-https://en.reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html。
请注意,以下代码的唯一目的是说明我的问题。它不是完整的代码。
App.js文件:
import React from 'react';
import './App.css';
import Display from './component.js'
class App extends React.Component {
state={resetCounter:false}
resetCounter= () => this.setState( {resetCounter: true} );
render() {
return (
<div className="App">
<header className="App-header">
<Display resetCounter={this.state.resetCounter}></Display>
<div>
<p></p><p></p>
<button onClick={this.resetCounter}>Reset</button>
</div>
</header>
</div>
);
}
componentDidUpdate () {
if (this.state.resetCounter!==false)
this.setState( {resetCounter: false} );
}
}
export default App;
component.js文件
import React from 'react'
class Display extends React.Component {
constructor() {
super();
this.state = this.resetState();
this.state.generalCounter=0;
}
/* method to avoid code duplication in constructor and cWRP
could not be used with getDerivedStateFromProps */
resetState = () => ({resettableCounter: 0,});
componentWillReceiveProps(nextProps) {
if (nextProps.resetCounter===true)
this.setState(this.resetState())
}
render() {
return (
<>
<div>
<div>general counter : {this.state.generalCounter}</div>
<div>resettable counter : {this.state.resettableCounter}</div>
</div>
<div>
<button onClick={this.incCounters}>+</button>
<button onClick={this.decCounters}>-</button>
</div>
</>
)
}
incCounters= () => this.setState(
{
resettableCounter: this.state.resettableCounter+1,
generalCounter: this.state.generalCounter+1
}
)
decCounters= () => this.setState(
{
resettableCounter: this.state.resettableCounter-1,
generalCounter: this.state.generalCounter-1
}
)
}
export default Display
在组件的状态下,有一个可重置的部分和一个不可重置的部分。方法resetState
用于避免在构造函数和cWRP中重复代码。
为了用gDSFP替换cWRP,我编写了一个类方法,因为无法在gDSFP中调用实例方法(this
不可用)
...
constructor() {
super();
this.state = Display.resetState();
this.state.generalCounter=0;
}
static resetState () {
return ({resettableCounter: 0,});
}
static getDerivedStateFromProps(nextProps) {
if (nextProps.resetCounter === true) {
return Display.resetState();
} else {
return null;
}
}
...
使用此解决方案,可以很容易地修改我的所有组件,但是我不确定这是一个好方法。
我想知道我是否有误解,是否应该重写我的组件以使用键(https://en.reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#preferred-solutions)将它们分为完全受控的组件和完全不受控制的组件。
例如,在这种情况下,我必须写:
我问这个问题是因为在某些情况下,这将需要大量工作,因此我想确定再继续。
答案 0 :(得分:0)
如果您的组件依赖于某些外部道具(您无法控制)(例如,返回的JSON或第3方渲染道具组件等),则您希望在帖子中保留gdsfp
版本。
您似乎完全可以控制传递给Display
的内容。您可以将初始resettableCounter
的值向下传递到Display
。
优点是双重的。
Display
道具展示了Display
的作用-使其更具描述性/可读性。对于您的特定情况,Fully uncontrolled component with a key
似乎更有意义,因为Display
应该接受要显示的初始值,但负责管理reseetableCounter
。
答案 1 :(得分:0)
除非这是绝对不可避免的,否则不要创建控制其兄弟姐妹(或父母)的组件。而是将状态提升为共同祖先:
const Display = ({
generalCounter,
resettableCounter,
incrementCounters,
decrementCounters,
}) => (
<div>
<div>General Counter: {generalCounter}</div>
<div>Resettable Counter: {resettableCounter}</div>
<button onClick={incrementCounters}>Increment</button>
<button onClick={decrementCounters}>Decrement</button>
</div>
);
class DisplayContainer extends React.Component {
state = {
generalCounter: 0,
resettableCounter: 0,
};
incrementCounters = () => this.setState(prevState => ({
generalCounter: prevState.generalCounter + 1,
resettableCounter: prevState.resettableCounter + 1,
}));
decrementCounters = () => this.setState(prevState => ({
generalCounter: prevState.generalCounter - 1,
resettableCounter: prevState.resettableCounter - 1,
}));
resetResettableCounter = () => this.setState({
resettableCounter: 0,
});
render() {
return (
<React.Fragment>
<Display
{...this.state}
incrementCounters={this.incrementCounters}
decrementCounters={this.decrementCounters}
/>
<button onClick={this.resetResettableCounter}>
Reset Resettable Counter
</button>
</React.Fragment>
);
}
}
const App = () => (
<div>
<DisplayContainer />
</div>
);
一种替代方法是类似Redux(可将状态有效地移出React)。