如何从Reactjs组件';s状态对象

如何从Reactjs组件';s状态对象,reactjs,state,Reactjs,State,如果我有一个在其状态上设置了属性的react组件: onClick() { this.setState({ foo: 'bar' }); } 是否可以从对象.key(this.state)中删除“foo” 该方法看起来像是显而易见的尝试方法,但后来被贬值了。您可以将foo设置为undefined,如下所示 var Hello = React.createClass({ getInitialState: function () { return {

如果我有一个在其状态上设置了属性的react组件:

onClick() {
    this.setState({ foo: 'bar' });
}
是否可以从
对象.key(this.state)
中删除
“foo”


该方法看起来像是显而易见的尝试方法,但后来被贬值了。

您可以将
foo
设置为
undefined
,如下所示

var Hello = React.createClass({
    getInitialState: function () {
        return {
            foo: 10,
            bar: 10
        }
    },

    handleClick: function () {
        this.setState({ foo: undefined });
    },

    render: function() {
        return (
            <div>
                <div onClick={ this.handleClick.bind(this) }>Remove foo</div>
                <div>Foo { this.state.foo }</div>
                <div>Bar { this.state.bar }</div>
            </div>
        );
    }
});

以前的解决方案-是反模式的,因为它会更改此.state。这是错误的

使用这个(旧方法):

或使用ES6糖:

this.setState({...o, a:undefined})
很甜蜜,不是吗?)

在旧的React语法(原始,而不是ES6)中,它有
this.replaceState
,可以删除存储中不必要的键,但现在它是您可以使用它在正确的深度创建应用程序状态的浅层副本,并从副本中删除元素。然后使用将修改后的副本合并回应用程序的状态

这不是一个完美的解决方案。这样复制整个对象可能会导致性能/内存问题<代码>对象。assign的浅拷贝有助于缓解内存/性能问题,但您还需要知道新对象的哪些部分是拷贝,哪些部分是对应用程序状态中数据的引用

在下面的示例中,修改
成分
数组实际上会直接修改应用程序状态

将不需要的元素的值设置为
null
undefined
不会删除它

const Component=React.Component;
类应用程序扩展组件{
建造师(道具){
超级(道具);
此.state={
“食谱”:{
"1": {
“id”:1,
“名字”:“南瓜派”,
“成分”:[
“南瓜泥”,
“加糖炼乳”,
“鸡蛋”,
“南瓜派香料”,
“馅饼皮”
]
},
"2": {
“id”:2,
“名称”:“意大利面”,
“成分”:[
“面条”,
“番茄酱”,
“(可选)肉丸”
]
},
"3": {
“id”:3,
“名字”:“洋葱派”,
“成分”:[
“洋葱”,
“馅饼皮”,
“鸡汤汤”
]
},
"4": {
“id”:4,
“名称”:“鸡汤面”,
“成分”:[
“鸡”,
“面条”,
“鸡汤”
]
}
},
“活动配方”:“4”,
“警告行动”:{
“名称”:“删除鸡汤面”,
“说明”:“删除鸡肉面条汤的配方”
}
};
this.renderRecipes=this.renderRecipes.bind(this);
this.deleteRecipe=this.deleteRecipe.bind(this);
}
删除配方(e){
const recipes=Object.assign({},this.state.recipes);
const id=e.currentTarget.dataset.id;
删除配方[id];
this.setState({recipes});
}
renderRecipes(){
常量配方=[];
for(此.state.recipes中的常量id){
推((
&时代;
{this.state.recipes[id].name}
));
}
返回食谱;
}
render(){
返回(
{this.renderRecipes()}
);
}
}
ReactDOM.render(,document.getElementById('app'))


GitHub上React源代码中的
ReactCompositeComponent.js
中的
是一个名为
\u processPendingState
的方法,它是实现从调用到component.setState的合并状态的最终方法

``` _processPendingState:函数(道具、上下文){ var inst=此实例; var queue=this._pendingStateQueue; var replace=此状态。_pendingReplaceState; 此项。_pendingReplaceState=false; 此。_pendingStateQueue=null

if (!queue) {
  return inst.state;
}

if (replace && queue.length === 1) {
  return queue[0];
}

var nextState = replace ? queue[0] : inst.state;
var dontMutate = true;
for (var i = replace ? 1 : 0; i < queue.length; i++) {
  var partial = queue[i];
  let partialState = typeof partial === 'function'
    ? partial.call(inst, nextState, props, context)
    : partial;
  if (partialState) {
    if (dontMutate) {
      dontMutate = false;
      nextState = Object.assign({}, nextState, partialState);
    } else {
      Object.assign(nextState, partialState);
    }
  }
}

此函数中没有调用
delete
或类似操作,这意味着这不是真正的预期行为。此外,完全复制stat、删除属性和调用setState都不起作用,因为setState始终是一个合并,所以删除的属性将被忽略

还要注意的是,setState不会立即工作,但会批量更改,因此,如果您尝试克隆整个state对象,并且只更改一个属性,则可能会忽略以前对setState的调用

React可以将多个setState()调用批处理到一个更新中以提高性能

由于this.props和this.state可能会异步更新,因此不应依赖它们的值来计算下一个状态

你能做的就是添加更多的信息

this.setState({ xSet: true, x: 'foo' });
this.setState({ xSet: false, x: undefined });

当然,这很难看,但它为您提供了额外的信息,您需要区分设置为未定义的值和未设置的值。此外,它还可以很好地处理React的内部结构、事务、状态更改批处理和任何其他恐怖行为。与其尝试猜测React的内部结构,不如在这里增加一点复杂性ch充满了交易对账、管理replaceState等不推荐使用的功能等恐怖行为

如果删除是在一个函数中,并且密钥需要是一个变量,请尝试以下操作:

removekey = (keyname) => {
    let newState = this.state;
    delete newState[keyname];
    this.setState(newState)
    // do not wrap the newState in additional curly braces  
}

this.removekey('thekey');

与steve的答案几乎相同,但在一个函数中。

如果您想完全重置状态(删除大量项目),类似的操作如下:

this.setState(prevState => {
    let newState = {};
    Object.keys(prevState).forEach(k => {
        newState[k] = undefined;
    });
    return newState;
});

使用此变量的
setState
允许您在调用期间访问整个状态,而
此.state
可能有点过时(由于之前的
setState
调用尚未完全处理)。

我认为这是一个很好的方法=>

//in constructor
let state = { 
   sampleObject: {0: a, 1: b, 2: c }
}

//method
removeObjectFromState = (objectKey) => {
   let reducedObject = {}
   Object.keys(this.state.sampleObject).map((key) => {
      if(key !== objectKey) reducedObject[key] = this.state.sampleObject[key];
   })
   this.setState({ sampleObject: reducedObject });
}
var Hello=React.createClass({
getInitialState:函数(){
返回{
傅:10,,
酒吧:10
}
},
handleClick:函数(){
让state={…this.state};
删除状态。
this.setState(prevState => {
    let newState = {};
    Object.keys(prevState).forEach(k => {
        newState[k] = undefined;
    });
    return newState;
});
//in constructor
let state = { 
   sampleObject: {0: a, 1: b, 2: c }
}

//method
removeObjectFromState = (objectKey) => {
   let reducedObject = {}
   Object.keys(this.state.sampleObject).map((key) => {
      if(key !== objectKey) reducedObject[key] = this.state.sampleObject[key];
   })
   this.setState({ sampleObject: reducedObject });
}
var Hello = React.createClass({
getInitialState: function () {
    return {
        foo: 10,
        bar: 10
    }
},

handleClick: function () {
    let state = {...this.state};
    delete state.foo;
    this.setState(state);
},

render: function() {
    return (
        <div>
            <div onClick={ this.handleClick.bind(this) }>Remove foo</div>
            <div>Foo { this.state.foo }</div>
            <div>Bar { this.state.bar }</div>
        </div>
    );
}
this.setState(prevState => {
            const newState = {
              formData: {
                ...prevState.formData,
                document_details: {
                  ...prevState.formData.document_details,
                  applicant: {
                    ...prevState.formData?.document_details?.applicant
                    keyToBeDeleted: dummVAlue //this is redundant
                  }
                }
              }
            };
            delete newState.formData.document_details.applicant.keyToBeDeleted;
            return newState;
          });