清除状态

我试图清除一个组件 state,但找不到 es6语法的参考:

this.replaceState(this.getInitialState());

但是这不适用于 es6类语法。

我怎样才能达到同样的结果呢?

182169 次浏览

据我所知,React 组件不保留初始状态的副本,所以您只能自己完成。

const initialState = {
/* etc */
};


class MyComponent extends Component {
constructor(props) {
super(props)
this.state = initialState;
}
reset() {
this.setState(initialState);
}
/* etc */
}

请注意,行 this.state = initialState;要求您永远不要突变您的状态,否则您将污染 initialState和使重置不可能。如果无法避免突变,那么需要在构造函数中创建 initialState的副本。(或者使 initialState成为一个函数,如 getInitialState()所示。)

最后,我建议您使用 setState()而不是 replaceState()

我将添加到上面的答案,重置函数也应该像这样分配状态:

reset() {
this.state = initialState;
this.setState(initialState);
}

原因是,如果您的状态选择了一个不处于初始状态的属性,那么这个键/值将不会被清除,因为 setState 只是更新现有的键。赋值不足以让组件重新呈现,所以还要包含 setState 调用——在赋值之后,您甚至可以使用 this.setState ({})。

我是这么处理的:

class MyComponent extends React.Component{
constructor(props){
super(props);
this._initState = {
a: 1,
b: 2
}
this.state = this._initState;
}


_resetState(){
this.setState(this._initState);
}
}

更新: 事实上,这是错误的。对于未来的读者,请参考@RaptoX 的答案。 另外,可以使用 Immutable 库来防止由引用分配引起的奇怪状态修改。

这是作为一种功能实现的解决方案:

Class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = this.getInitialState();
}


getInitialState = () => ({
/* state props */
})


resetState = () => {
this.setState(this.getInitialState());
}
}

首先,在使用组件生命周期中的 componentWillMount()函数时,需要存储初始状态:

componentWillMount() {
this.initialState = this.state
}

这将存储您的初始状态,并且可以在需要时通过调用

this.setState(this.initialState)

直接设置 this.state的解决方案在反应16中对我不起作用,所以下面是我重新设置每个键的方法:

  const initialState = { example: 'example' }
...
constructor() {
super()
this.state = initialState
}
...
reset() {
const keys = Object.keys(this.state)
const stateReset = keys.reduce((acc, v) => ({ ...acc, [v]: undefined }), {})
this.setState({ ...stateReset, ...initialState })
}

问题

返回文章页面 接受的答案:

const initialState = {
/* etc */
};


class MyComponent extends Component {
constructor(props) {
super(props)
this.state = initialState;
}
reset() {
this.setState(initialState);
}
/* etc */
}

不幸的是 不对

initialState是作为对 this.state的引用传递的,因此每当您更改 state时,您也会更改 initialState(康斯特在这里并不重要)。结果就是你再也回不到 initialState了。

解决方案

你必须 深度拷贝 initialStatestate,然后它将工作。要么自己编写一个深度复制函数,要么使用一些现有的模块,比如 这个

class x extends Components {
constructor() {
super();
this.state = {


name: 'mark',
age: 32,
isAdmin: true,
hits: 0,


// since this.state is an object
// simply add a method..


resetSelectively() {
//i don't want to reset both name and age
// THIS IS FOR TRANSPARENCY. You don't need to code for name and age
// it will assume the values in default..
// this.name = this.name;   //which means the current state.
// this.age = this.age;




// do reset isAdmin and hits(suppose this.state.hits is 100 now)


isAdmin = false;
hits = 0;
}// resetSelectively..


}//constructor..


/* now from any function i can just call */
myfunction() {
/**
* this function code..
*/
resetValues();


}// myfunction..


resetValues() {
this.state.resetSelectively();
}//resetValues


/////
//finally you can reset the values in constructor selectively at any point


...rest of the class..


}//class
const initialState = {
a: '',
b: '',
c: ''
};


class ExampleComponent extends Component {
state = { ...initialState } // use spread operator to avoid mutation
handleReset = this.handleReset.bind(this);


handleReset() {
this.setState(initialState);
}
}

请记住,为了能够重置状态,不要变异 initialState 非常重要。

state = {...initialState} // GOOD
// => state points to a new obj in memory which has the values of initialState


state = initialState // BAD
// => they point to the same obj in memory

最方便的方法是使用 ES6扩展运算符。但是您也可以使用 Object.sign 来代替。他们都会得到同样的结果。

state = Object.assign({}, initialState); // GOOD
state = {...initialState}; // GOOD

在大多数情况下,您不需要一个深拷贝,很少初始状态是对象的对象,所以使用 babel 传递给 object.sign 的扩展运算符应该没问题。

所以,在构造函数内部你会有:

class MyComponent extends Component {
constructor(props) {
super(props)
this.state = {
key: value,
key2: value
}
this.initialState = { ...this.state }
}
}

从那里你可以使用

this.setState(this.initialState);

但是如果由于某种原因你的初始状态是更复杂的对象,使用一些库。

在某些情况下,只需将 state的所有值设置为 null即可。

如果您的状态以这样的方式更新,您不知道其中可能包含什么,那么您可能需要使用

this.setState(Object.assign(...Object.keys(this.state).map(k => ({[k]: null}))))

它将按如下方式改变状态

{foo: 1, bar: 2, spam: "whatever"} > {foo: null, bar: null, spam: null}

不是所有情况下的解决方案,但对我很有效。

您可以克隆状态对象,循环遍历每个对象,并将其设置为 undefined。但是,这种方法并不像公认的答案那样好。

const clonedState = this.state;


const keys = Object.keys(clonedState);
keys.forEach(key => (clonedState[key] = undefined));


this.setState(clonedState);
class MyComponent extends Component {
constructor(props){
super(props)
this.state = {
inputVal: props.inputValue
}
// preserve the initial state in a new object
this.baseState = this.state
}
resetForm = () => {
this.setState(this.baseState)
}


}

使用 deep copy,你可以使用 loash:

import _ from "lodash";


const INITIAL_STATE = {};


constructor(props) {
super(props);
this.state = _.cloneDeep(INITIAL_STATE);
}


reset() {
this.setState(_.cloneDeep(INITIAL_STATE));
}