我试图通过使用这样的嵌套属性来组织我的状态:

this.state = {
   someProperty: {
      flag:true
   }
}

但是像这样更新状态,

this.setState({ someProperty.flag: false });

是行不通的。怎样才能正确地做到这一点呢?


当前回答

使用箭头函数代替,这应该做的把戏。

setItems((prevState) => {
   prevState.nestedData = newNestedData;
   prevState.nestedData1 = newNestedData1;
});

不要忘记使用箭头函数(prevState) =>{更新js赋值语句…}

其他回答

还有两个选项没有提到:

如果您有深度嵌套的状态,请考虑是否可以重新构造子对象,使其位于根节点。这使得数据更容易更新。 Redux文档中列出了许多方便的库来处理不可变状态。我推荐Immer,因为它允许您以可变的方式编写代码,但在幕后处理必要的克隆。它还会冻结生成的对象,这样以后就不会意外地改变它。

有时候直接回答并不是最好的答案:)

短版:

这段代码

this.state = {
    someProperty: {
        flag: true
    }
}

应该简化成这样吗

this.state = {
    somePropertyFlag: true
}

长版:

目前你不应该在React中使用嵌套状态。因为React不是面向嵌套状态的,这里提出的所有解决方案看起来都是hack。他们不使用框架,而是与之斗争。他们建议为了分组某些属性的可疑目的而编写不那么清晰的代码。所以它们作为挑战的答案是非常有趣的,但实际上毫无用处。

让我们想象一下下面的状态:

{
    parent: {
        child1: 'value 1',
        child2: 'value 2',
        ...
        child100: 'value 100'
    }
}

如果只改变child1的值会发生什么?React不会重新渲染视图,因为它使用浅比较,它会发现父属性没有改变。顺便说一句,直接改变状态对象通常被认为是一种糟糕的做法。

所以你需要重新创建整个父对象。但在这种情况下,我们会遇到另一个问题。React会认为所有的孩子都改变了他们的价值观,并重新渲染所有的孩子。当然,这对性能没有好处。

通过在shouldComponentUpdate()中编写一些复杂的逻辑仍然可以解决这个问题,但我宁愿在这里停下来,使用简短版本中的简单解决方案。

setInputState((pre)=> ({...pre,[parentKey]: {...pre[parentKey], [childKey]: value}}));

我喜欢这个

根据框架的标准,不确定这在技术上是否正确,但有时您只是需要更新嵌套对象。这是我使用钩子的解决方案。

setInputState ({ ... inputState, [括号]:内务部[括号],[childKey]: });

这是我的initialState

    const initialStateInput = {
        cabeceraFamilia: {
            familia: '',
            direccion: '',
            telefonos: '',
            email: ''
        },
        motivoConsulta: '',
        fechaHora: '',
        corresponsables: [],
    }

钩子或者你可以用状态(类组件)替换它

const [infoAgendamiento, setInfoAgendamiento] = useState(initialStateInput);

handleChange的方法

const actualizarState = e => {
    const nameObjects = e.target.name.split('.');
    const newState = setStateNested(infoAgendamiento, nameObjects, e.target.value);
    setInfoAgendamiento({...newState});
};

使用嵌套状态设置状态的方法

const setStateNested = (state, nameObjects, value) => {
    let i = 0;
    let operativeState = state;
    if(nameObjects.length > 1){
        for (i = 0; i < nameObjects.length - 1; i++) {
            operativeState = operativeState[nameObjects[i]];
        }
    }
    operativeState[nameObjects[i]] = value;
    return state;
}

最后这是我使用的输入

<input type="text" className="form-control" name="cabeceraFamilia.direccion" placeholder="Dirección" defaultValue={infoAgendamiento.cabeceraFamilia.direccion} onChange={actualizarState} />