如何在React中更新嵌套状态属性


389

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

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

但是像这样更新状态

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

不起作用。如何正确完成?


4
你什么意思不起作用?这不是一个很好的问题-发生了什么?有什么错误吗?有什么错误?
Darren Sweeney


16
答案是不要在React中使用嵌套状态。阅读这个出色的答案。
Qwerty

4
应该用什么代替呢?
贾尼斯·埃默里斯(JānisElmeris)

42
对于当今React的广泛使用,简单地不使用嵌套状态是不可接受的答案。这种情况将要出现,开发人员需要对此的答案。
serraosays

Answers:


454

为了setState创建嵌套对象,您可以按照以下方法进行操作,因为我认为setState无法处理嵌套更新。

var someProperty = {...this.state.someProperty}
someProperty.flag = true;
this.setState({someProperty})

想法是创建一个虚拟对象,对其执行操作,然后用更新的对象替换组件的状态

现在,散布运算符仅创建对象的一级嵌套副本。如果您的状态是高度嵌套的,例如:

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

您可以在每个级别使用传播运算符来设置状态,例如

this.setState(prevState => ({
    ...prevState,
    someProperty: {
        ...prevState.someProperty,
        someOtherProperty: {
            ...prevState.someProperty.someOtherProperty, 
            anotherProperty: {
               ...prevState.someProperty.someOtherProperty.anotherProperty,
               flag: false
            }
        }
    }
}))

但是,随着状态的嵌套越来越多,上述语法变得越来越难看,因此我建议您使用 immutability-helper package更新状态。

有关如何使用更新状态的信息,请参见此答案immutability helper


2
@Ohgodwhy,不,这不是因为{... this.state.someProperty}重新向新对象迁移someProperty,所以我们不能直接访问该州,我们正在对此进行修改
Shubham Khatri

4
这对我不起作用..我使用的是React版本@ 15.6.1
Rajiv,

5
@Stophface我们可以肯定地使用Lodash来进行深度克隆,但是并不是每个人都将这个库包含在setState中
Shubham Khatri

15
这不违反reactjs.org/docs/…吗?如果对嵌套对象进行了两次更改,则最后一次更改将覆盖第一个更改。因此,最正确的方法是:this.setState((prevState) => ({nested: {...prevState.nested, propertyToSet: newValue}}) 虽然有点乏味……
olejorgenb

2
我认为您...prevState,在最后一个示例中不需要,仅您someProperty和它的孩子
Jemar Jones

140

一行编写

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

12
建议对setState使用更新程序,而不是直接在setState中访问this.state。reactjs.org/docs/react-component.html#setstate
Raghu Teja

6
我相信这是在说,不要this.state在此之后立即阅读setState并期望它具有新的价值。对战通话this.statesetState。还是后者还有一个我不清楚的问题?
trpt4him

2
正如trpt4him所说,您提供的链接讨论了this.stateafter之后的访问问题setState。此外,我们没有传递this.statesetState。该运营商扩展性。它与Object.assign()相同。github.com/tc39/proposal-object-rest-spread
Yoseph

3
@RaghuTeja也许 this.setState(currentState => { someProperty: { ...currentState.someProperty, flag: false} });可以避免这个问题?
Webwoman

我已经添加了答案,如何通过useState挂钩实现相同性以实现完整性。
安德鲁(Andrew)

89

有时直接答案不是最佳答案:)

简洁版本:

此代码

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

应该简化为类似

this.state = {
    somePropertyFlag: true
}

长版:

当前,您不应该在React中使用嵌套状态。因为React不适合与嵌套状态一起使用,并且这里提出的所有解决方案看起来都是骇客。他们不使用框架而是与之抗争。他们建议编写不太清晰的代码,以便对某些属性进行分组。因此,它们作为应对挑战的方式非常有趣,但实际上没有用。

让我们想象一下以下状态:

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

如果仅更改一个值,将会发生什么child1?React不会重新渲染视图,因为它使用浅表比较,并且会发现该parent属性没有改变。通常,将BTW直接更改为状态对象是一种不良做法。

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

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


4
我认为在某些情况下,嵌套状态会很好。例如,动态跟踪键值对的状态。看到这里,你怎么能在该州只是一个单一的条目更新状态:reactjs.org/docs/...
PORS

1
默认情况下,浅比较用于纯组件。
巴塞尔Shishani

4
我想为您创建一个祭坛,并每天早晨向其祈祷。我花了三天的时间才能完全回答这个显而易见的设计决定。每个人都只是尝试使用传播运算符或进行其他黑客攻击,只是因为嵌套状态看起来更易于理解。
Edeph '18

1
那么,您如何建议使用React进行渲染交互式树之类的工作(例如,我的公司在世界不同地区拥有一堆传感器,每个传感器在不同的位置,具有不同的属性,并且在不同的位置(80+ )和课程,它们按层次结构进行组织,因为每个部署都要花费数千美元,并且是一个完整的项目,因此如果没有层次结构就无法管理它们。我很好奇您如何在React中不像树一样建模树。
DanyAlejandro

10
似乎React并不是用来表示任何存储为非平凡深度的递归结构的东西。令人失望的是,树视图几乎出现在其中的每个复杂应用程序(gmail,文件管理器,任何文档管理系统等等)中。我已经使用React来做这些事情,但是总是有一个React狂热者告诉每个人您正在做反模式,并建议该解决方案将树的深层副本保持在每个节点的状态(是,共80个副本)。我很乐意看到一个不会破解任何React规则的非hacky树视图组件。
DanyAlejandro

61

免责声明

React中的嵌套状态是错误的设计

阅读这个出色的答案

 

这个答案背后的原因:

React的setState只是一个内置的便利,但是您很快就会意识到它有其局限性。使用自定义属性和智能使用forceUpdate可为您提供更多服务。例如:

class MyClass extends React.Component {
    myState = someObject
    inputValue = 42
...

例如,MobX完全保留状态并使用自定义的可观察属性。
使用Observables代替React组件中的状态。

 


苦难的答案- 在这里查看示例

还有另一种更短的方法来更新任何嵌套属性。

this.setState(state => {
  state.nested.flag = false
  state.another.deep.prop = true
  return state
})

一行上

 this.setState(state => (state.nested.flag = false, state))

注意:这是逗号运算符〜MDN,在这里可以看到它的作用(沙盒)

它类似于(尽管这不会更改状态引用)

this.state.nested.flag = false
this.forceUpdate()

有关此上下文之间的细微差别forceUpdatesetState请参见链接的示例。

当然,这是在滥用一些核心原则,因为它们state应该是只读的,但是由于您将立即丢弃旧状态并将其替换为新状态,因此完全可以。

警告

即使包含状态的组件正确更新和重新渲染此陷阱除外,道具也不会传播给子对象(请参阅下面的Spymaster的评论)。仅当您知道自己在做什么时才使用此技术。

例如,您可以传递一个易于更新和传递的更改后的平面道具。

render(
  //some complex render with your nested state
  <ChildComponent complexNestedProp={this.state.nested} pleaseRerender={Math.random()}/>
)

现在,即使对complexNestedProp的引用没有更改(shouldComponentUpdate

this.props.complexNestedProp === nextProps.complexNestedProp

每当父组件更新时,该组件将重新呈现(在调用后this.setStatethis.forceUpdate在父组件中)。

改变状态的影响

使用嵌套的状态,并直接变异状态是危险的,因为不同的对象可能会保留(有意或无意)的不同(以上)引用的状态和可能不一定什么时候更新知道(当使用例如PureComponent,或者shouldComponentUpdate被实现为回报false有旨在显示旧数据,如以下示例所示。

想象一下应该渲染历史数据的时间轴,对手底数据进行突变会导致意外行为,因为它还会更改以前的项目。

状态流 状态流嵌套

无论如何,您可以在这里看到Nested PureChildClass由于道具传播失败而未重新渲染。


12
您不应该在任何地方改变任何反应状态。如果有嵌套的组件使用来自state.nested或state.another的数据,则它们将不会重新渲染,也不会重新渲染其子级。这是因为对象没有改变,因此React认为没有任何改变。
Zeragamba

@ SpyMaster356我已更新我的答案以解决此问题。另请注意,例如MobX会state完全沟渠并使用自定义的可观察属性。React setState只是内置的便利,但是您很快就会意识到它有其局限性。使用自定义属性和智能使用可以forceUpdate给您带来更多的收益。使用Observables代替React组件中的状态。
Qwerty

我还添加了一个示例react-experiments.herokuapp.com/state-flow(链接到顶部的git)
Qwerty

例如,如果您将具有嵌套属性的对象从数据库加载到状态中该怎么办?在这种情况下如何避免嵌套状态?
tobiv

3
@tobiv最好将获取时的数据转换为不同的结构,但这取决于用例。如果您将嵌套对象或对象数组视为某些数据的紧凑单元,则可以处于状态中。当您需要存储UI开关或其他可观察的数据(即应立即更改视图的数据)时会出现问题,因为它们必须是平坦的才能正确触发内部React差异算法。对于其他嵌套对象的更改,很容易触发this.forceUpdate()或实现specific shouldComponentUpdate
Qwerty

21

如果您使用的是ES2015,则可以访问Object.assign。您可以如下使用它来更新嵌套对象。

this.setState({
  someProperty: Object.assign({}, this.state.someProperty, {flag: false})
});

您将更新后的属性与现有属性合并,并使用返回的对象来更新状态。

编辑:将一个空对象作为目标分配给assign函数,以确保状态不会像carkod所指出的那样直接突变。


12
我可能是错的,但我不认为您在没有 ES2015的情况下使用React 。
Madbreaks'Nov

16
const newState = Object.assign({}, this.state);
newState.property.nestedProperty = "new value";
this.setState(newState);

1
在这里似乎是更优雅的解决方案,1)避免在setState内部繁琐的传播,以及2)在setState内部很好地放置新状态,避免直接在setState内部进行突变。最后但并非最不重要的3)避免仅使用一个简单的任务就可以使用任何库
Webwoman

这两个例子并不等效。如果property包含多个嵌套属性,则第一个将删除它们,第二个则不会。codeandbox.io/s/nameless-pine-42thu
Qwerty

Qwerty,您是对的,感谢您的努力。我删除了ES6版本。
eyecandy.dev

简单明了!
Tony Sepia

我用你的解决方案。我的状态obj很小,并且工作正常。React是只为更改后的状态渲染还是会渲染所有内容?
野口健二

14

有很多库可以帮助您解决此问题。例如,使用immutability-helper

import update from 'immutability-helper';

const newState = update(this.state, {
  someProperty: {flag: {$set: false}},
};
this.setState(newState);

使用lodash / fp设置:

import {set} from 'lodash/fp';

const newState = set(["someProperty", "flag"], false, this.state);

使用lodash / fp合并:

import {merge} from 'lodash/fp';

const newState = merge(this.state, {
  someProperty: {flag: false},
});

如果使用lodash,则可能要尝试_.cloneDeep将state设置为克隆副本。
宜兴刘

@YixingLiu:我已经更新了use的答案lodash/fp,所以我们不必担心突变。
tokland

除了语法以外,在lodash / fp中进行选择mergeset运行还有什么好处?
ToivoSäwén

好的答案,也许您想补充一点,您也必须调用this.setState(newState)lodash / fp方法。另一个陷阱是,lodash .set(非fp)具有不同顺序的参数,这使我绊了一会儿。
ToivoSäwén

7

我们使用Immer https://github.com/mweststrate/immer处理此类问题。

只是在我们的组件之一中替换了此代码

this.setState(prevState => ({
   ...prevState,
        preferences: {
            ...prevState.preferences,
            [key]: newValue
        }
}));

有了这个

import produce from 'immer';

this.setState(produce(draft => {
    draft.preferences[key] = newValue;
}));

通过沉浸,您可以将状态视为“正常对象”。魔术发生在具有代理对象的幕后。


6

这是此线程中给出的第一个答案的变体,不需要任何额外的程序包,库或特殊功能。

state = {
  someProperty: {
    flag: 'string'
  }
}

handleChange = (value) => {
  const newState = {...this.state.someProperty, flag: value}
  this.setState({ someProperty: newState })
}

为了设置特定嵌套字段的状态,您已经设置了整个对象。为此,我创建了一个变量,newState首先使用ES2015 Spread 运算符将当前状态的内容扩展到其中。然后,我用this.state.flag新值替换了值(因为flag: value 将当前状态散布到对象中后进行设置所以当前状态中的flag字段将被覆盖)。然后,我简单地设置的状态someProperty到我的newState对象。


6

尽管嵌套并不是您应该如何对待组件状态,但有时对于单层嵌套来说还是很容易的。

对于这样的状态

state = {
 contact: {
  phone: '888-888-8888',
  email: 'test@test.com'
 }
 address: {
  street:''
 },
 occupation: {
 }
}

我所使用的可重用方法如下所示。

handleChange = (obj) => e => {
  let x = this.state[obj];
  x[e.target.name] = e.target.value;
  this.setState({ [obj]: x });
};

然后只需为您要寻址的每个嵌套传递obj名称...

<TextField
 name="street"
 onChange={handleChange('address')}
 />

4

我用了这个解决方案。

如果您有这样的嵌套状态:

   this.state = {
          formInputs:{
            friendName:{
              value:'',
              isValid:false,
              errorMsg:''
            },
            friendEmail:{
              value:'',
              isValid:false,
              errorMsg:''
            }
}

您可以声明handleChange函数,该函数复制当前状态并使用更改后的值重新分配它

handleChange(el) {
    let inputName = el.target.name;
    let inputValue = el.target.value;

    let statusCopy = Object.assign({}, this.state);
    statusCopy.formInputs[inputName].value = inputValue;

    this.setState(statusCopy);
  }

这里的HTML与事件监听器

<input type="text" onChange={this.handleChange} " name="friendName" />

已确认。如果您已经在处理一个带有嵌套属性的已建立项目,则此方法非常有用。
metal_jacke1

4

创建状态的副本:

let someProperty = JSON.parse(JSON.stringify(this.state.someProperty))

在此对象中进行更改:

someProperty.flag = "false"

现在更新状态

this.setState({someProperty})

setState是异步的。因此,在更新时,其他人可以调用此函数并复制该状态的过时版本。
阿维夫·本·沙巴特

3

尽管您询问了基于类的React组件的状态,但useState钩子也存在相同的问题。更糟糕的是:useState钩子不接受部分更新。因此,当引入useState挂钩时,此问题变得非常相关。

我决定发布以下答案,以确保问题涵盖使用useState挂钩的更现代的方案:

如果您有:

const [state, setState] = useState({ someProperty: { flag: true, otherNestedProp: 1 }, otherProp: 2 })

您可以通过克隆当前数据并修补所需的数据段来设置嵌套属性,例如:

setState(current => { ...current, someProperty: { ...current.someProperty, flag: false } });

或者,您可以使用Immer库来简化对象的克隆和修补。

或者,您可以使用Hookstate库(免责声明:我是作者)来简单地完全管理复杂(本地和全局)状态数据并提高性能(阅读:不必担心渲染优化):

import { useStateLink } from '@hookstate/core' 
const state = useStateLink({ someProperty: { flag: true, otherNestedProp: 1 }, otherProp: 2 })

获取要渲染的字段:

state.nested.someProperty.nested.flag.get()
// or 
state.get().someProperty.flag

设置嵌套字段:

state.nested.someProperty.nested.flag.set(false)

这是Hookstate的示例,其中状态被深度/递归嵌套在树状数据结构中


2

尚未提及的其他两个选项:

  1. 如果您具有深层嵌套的状态,请考虑是否可以重组子对象以使其位于根目录。这使数据更易于更新。
  2. Redux文档中列出了许多方便的库来处理不可变状态。我建议使用Immer,因为它允许您以可变的方式编写代码,但可以处理后台的必要克隆。它还会冻结结果对象,因此您以后不会意外对其进行突变。

2

为了使事情变得通用,我研究了@ShubhamKhatri和@Qwerty的答案。

状态对象

this.state = {
  name: '',
  grandParent: {
    parent1: {
      child: ''
    },
    parent2: {
      child: ''
    }
  }
};

输入控件

<input
  value={this.state.name}
  onChange={this.updateState}
  type="text"
  name="name"
/>
<input
  value={this.state.grandParent.parent1.child}
  onChange={this.updateState}
  type="text"
  name="grandParent.parent1.child"
/>
<input
  value={this.state.grandParent.parent2.child}
  onChange={this.updateState}
  type="text"
  name="grandParent.parent2.child"
/>

updateState方法

setState为@ShubhamKhatri的答案

updateState(event) {
  const path = event.target.name.split('.');
  const depth = path.length;
  const oldstate = this.state;
  const newstate = { ...oldstate };
  let newStateLevel = newstate;
  let oldStateLevel = oldstate;

  for (let i = 0; i < depth; i += 1) {
    if (i === depth - 1) {
      newStateLevel[path[i]] = event.target.value;
    } else {
      newStateLevel[path[i]] = { ...oldStateLevel[path[i]] };
      oldStateLevel = oldStateLevel[path[i]];
      newStateLevel = newStateLevel[path[i]];
    }
  }
  this.setState(newstate);
}

setState作为@Qwerty的答案

updateState(event) {
  const path = event.target.name.split('.');
  const depth = path.length;
  const state = { ...this.state };
  let ref = state;
  for (let i = 0; i < depth; i += 1) {
    if (i === depth - 1) {
      ref[path[i]] = event.target.value;
    } else {
      ref = ref[path[i]];
    }
  }
  this.setState(state);
}

注意:以上方法不适用于数组


2

我非常重视围绕创建组件状态的完整副本已经表达的担忧。话虽如此,我强烈建议Immer

import produce from 'immer';

<Input
  value={this.state.form.username}
  onChange={e => produce(this.state, s => { s.form.username = e.target.value }) } />

这应该适用于React.PureComponent(即React进行的浅层状态比较),因为它Immer巧妙地使用了代理对象来有效地复制任意深层状态树。与Immutability Helper之类的库相比,Immer还具有更好的类型安全性,是Javascript和Typescript用户的理想选择。


打字稿实用程序功能

function setStateDeep<S>(comp: React.Component<any, S, any>, fn: (s: 
Draft<Readonly<S>>) => any) {
  comp.setState(produce(comp.state, s => { fn(s); }))
}

onChange={e => setStateDeep(this, s => s.form.username = e.target.value)}

1
stateUpdate = () => {
    let obj = this.state;
    if(this.props.v12_data.values.email) {
      obj.obj_v12.Customer.EmailAddress = this.props.v12_data.values.email
    }
    this.setState(obj)
}

1
我认为这是不对的,因为obj这只是对国家的引用,因此您正在通过它来改变实际的this.state对象
CiprianTomoiagă19年

0

我发现这对我有用,在我的情况下有一个项目表单,例如您有一个ID和一个名称,而我宁愿维护嵌套项目的状态。

return (
  <div>
      <h2>Project Details</h2>
      <form>
        <Input label="ID" group type="number" value={this.state.project.id} onChange={(event) => this.setState({ project: {...this.state.project, id: event.target.value}})} />
        <Input label="Name" group type="text" value={this.state.project.name} onChange={(event) => this.setState({ project: {...this.state.project, name: event.target.value}})} />
      </form> 
  </div>
)

让我知道!


0

这样的事情可能就足够了,

const isObject = (thing) => {
    if(thing && 
        typeof thing === 'object' &&
        typeof thing !== null
        && !(Array.isArray(thing))
    ){
        return true;
    }
    return false;
}

/*
  Call with an array containing the path to the property you want to access
  And the current component/redux state.

  For example if we want to update `hello` within the following obj
  const obj = {
     somePrimitive:false,
     someNestedObj:{
        hello:1
     }
  }

  we would do :
  //clone the object
  const cloned = clone(['someNestedObj','hello'],obj)
  //Set the new value
  cloned.someNestedObj.hello = 5;

*/
const clone = (arr, state) => {
    let clonedObj = {...state}
    const originalObj = clonedObj;
    arr.forEach(property => {
        if(!(property in clonedObj)){
            throw new Error('State missing property')
        }

        if(isObject(clonedObj[property])){
            clonedObj[property] = {...originalObj[property]};
            clonedObj = clonedObj[property];
        }
    })
    return originalObj;
}

const nestedObj = {
    someProperty:true,
    someNestedObj:{
        someOtherProperty:true
    }
}

const clonedObj = clone(['someProperty'], nestedObj);
console.log(clonedObj === nestedObj) //returns false
console.log(clonedObj.someProperty === nestedObj.someProperty) //returns true
console.log(clonedObj.someNestedObj === nestedObj.someNestedObj) //returns true

console.log()
const clonedObj2 = clone(['someProperty','someNestedObj','someOtherProperty'], nestedObj);
console.log(clonedObj2 === nestedObj) // returns false
console.log(clonedObj2.someNestedObj === nestedObj.someNestedObj) //returns false
//returns true (doesn't attempt to clone because its primitive type)
console.log(clonedObj2.someNestedObj.someOtherProperty === nestedObj.someNestedObj.someOtherProperty) 

0

我知道这是一个古老的问题,但仍然想分享我是如何实现的。假设构造函数中的状态如下所示:

  constructor(props) {
    super(props);

    this.state = {
      loading: false,
      user: {
        email: ""
      },
      organization: {
        name: ""
      }
    };

    this.handleChange = this.handleChange.bind(this);
  }

我的handleChange功能是这样的:

  handleChange(e) {
    const names = e.target.name.split(".");
    const value = e.target.type === "checkbox" ? e.target.checked : e.target.value;
    this.setState((state) => {
      state[names[0]][names[1]] = value;
      return {[names[0]]: state[names[0]]};
    });
  }

并确保您相应地命名输入:

<input
   type="text"
   name="user.email"
   onChange={this.handleChange}
   value={this.state.user.firstName}
   placeholder="Email Address"
/>

<input
   type="text"
   name="organization.name"
   onChange={this.handleChange}
   value={this.state.organization.name}
   placeholder="Organization Name"
/>

0

我使用减少搜索来嵌套更新:

例:

嵌套变量的状态:

state = {
    coords: {
        x: 0,
        y: 0,
        z: 0
    }
}

功能:

handleChange = nestedAttr => event => {
  const { target: { value } } = event;
  const attrs = nestedAttr.split('.');

  let stateVar = this.state[attrs[0]];
  if(attrs.length>1)
    attrs.reduce((a,b,index,arr)=>{
      if(index==arr.length-1)
        a[b] = value;
      else if(a[b]!=null)
        return a[b]
      else
        return a;
    },stateVar);
  else
    stateVar = value;

  this.setState({[attrs[0]]: stateVar})
}

采用:

<input
value={this.state.coords.x}
onChange={this.handleTextChange('coords.x')}
/>

0

这是我的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} />

0

如果您在项目中使用formik,则有一些简单的方法可以处理这些问题。这是使用Formik最简单的方法。

首先在formik initivalues属性或react中设置您的初始值。州

在此,初始值在反应状态下定义

   state = { 
     data: {
        fy: {
            active: "N"
        }
     }
   }

在formik initiValues属性内为formik字段定义上述initialValues

<Formik
 initialValues={this.state.data}
 onSubmit={(values, actions)=> {...your actions goes here}}
>
{({ isSubmitting }) => (
  <Form>
    <Field type="checkbox" name="fy.active" onChange={(e) => {
      const value = e.target.checked;
      if(value) setFieldValue('fy.active', 'Y')
      else setFieldValue('fy.active', 'N')
    }}/>
  </Form>
)}
</Formik>

使控制台检查更新到的状态,string而不是boolean使用formik setFieldValue函数来设置状态,或者使用react调试器工具查看formik状态值中的更改。


0

试试这个代码:

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

但这将删除someProperty在上述代码执行后引用的对象中存在的所有其他属性,只有该flag属性会保留
Yashas

0

我在一本书中看到以下内容:

this.setState(state => state.someProperty.falg = false);

但我不确定是否正确..

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.