ReactJS:如何使用动态键访问和更新嵌套状态对象?

Posted

技术标签:

【中文标题】ReactJS:如何使用动态键访问和更新嵌套状态对象?【英文标题】:ReactJS: How to access and update nested state object with dynamic key? 【发布时间】:2019-10-06 12:33:27 【问题描述】:

假设我有一个状态定义如下的组件:

this.state = 
    apple:
        a:1,
        b:2,
    ,
    mango:
        banana : 
            a:1,
            b:2,
        
    

如果我想在我的状态下更新嵌套对象的值,我可以使用如下所示的硬编码键来执行此操作:

cost temp =   ...this.state['mango'] 
temp['banana']['a'] = 2;

this.setState(mango:temp);

如何动态更新状态对象中的嵌套值?例如,如果我有一个点或数组表示法的 JSON 路径,我如何更新我的组件状态?

【问题讨论】:

如何提供输入以便您可以动态访问这些键? 使用点符号或数组 【参考方案1】:

实现此目的的一种方法是通过Array#reduce 获取作为路径所针对的字段的父级的嵌套对象:

const nestedObject = path
.slice(0, -1)
.reduce((object, part) => (object === undefined ? undefined : object[part]),  ...state )

然后通过路径的最后一个键更新nestedObject 的最后一个键/值:

/* Get last part of path, and update nestedObject's value for this key, to 2 */
const [pathTail] = path.slice(-1);    
nestedObject[pathTail] = 2;

下面的sn-p将这两个想法一起展示:

/* Path of nested field to update, in array notation */
const path = ['mango', 'banana', 'a'];

/* Components state */
const state = 
  apple: 
    a: 1,
    b: 2,
  ,
  mango: 
    banana: 
      a: 1,
      b: 2,
    
  
;

const stateClone =  ...state ;

/* Aquire the parent object (ie banana) of the target field (ie a) */
const nestedObject = path
.slice(0, -1)
.reduce((object, part) => (object === undefined ? undefined : object[part]), stateClone)

if (nestedObject !== undefined) 

  /* Obtain last key in path */
  const [pathTail] = path.slice(-1);

  /* Update value of last key on target object to new value */
  nestedObject[pathTail] = 2;


/* Display updated state */
console.log('Updated state:', stateClone)

/* Call this.setState: */
// this.setState(stateClone);

更新

这里有一些额外的细节概述了答案的reduce() 部分是如何工作的:

path
/* slice obtains ['mango', 'banana'], seeing -1 clips last item */
.slice(0, -1)  
/* reduce iterates through each part of array ['mango', 'banana']
where at each iteration we fetch the corresponding nested object 
of the  ...state  object that's passed in */
.reduce((object, part) => 

/* At iteration 1: 
object has two keys, 'apple' and 'mango'
part is 'mango'
object is defined, so return object['mango'] for first iteration

At iteration 2:
object passed from last iteration has one key, 'banana'
part is 'banana'
object is defined, so return object['banana'] for second iteration

Reduce complete:
we return object['banana'], which is the same as state['mango']['banana']
*/

if(object === undefined)  return undefined; 

return object[part]

, stateClone)

【讨论】:

你是很棒的兄弟,你能再帮我一个忙吗?请在你的例子中解释一下reduce函数 不客气,很高兴我能帮上忙!当然,我会更详细地更新我的答案:-) 它工作正常,但状态的变化在我为任何其他变量设置状态之前不会反映出来 是的,您需要将上面的stateClone 对象传递给setState() 以使组件根据新状态进行更新 是的,现在它与状态克隆一起工作正常,它的速度也提高了【参考方案2】:

拥有:

 const [formState, setFormState] = useState(
      
        id:1,
        name:'Name',
        innerObjectName: 
            propA: 'Something',
            propB: 'Another thing',
        
      );

也许你正在寻找这样的东西:

   const handleComplexInputChange = (evt, object) => 
      setFormState(
         ...formState,
         [object] : 
            ...formState[object],
            [evt.target.name]: evt.target.value,
         
      )
    

从你的组件中你应该这样称呼它:

   onChange=(e) => 
        handleComplexInputChange(e, "innerObjectName");
   

【讨论】:

以上是关于ReactJS:如何使用动态键访问和更新嵌套状态对象?的主要内容,如果未能解决你的问题,请参考以下文章

ReactJS - 如何更新嵌套和“正常”状态属性?

基于 reactJS 中的 props 使用动态键初始化状态

ReactJS进度条使用状态动态更新?

ReactJS - 更新后子级无法访问父级状态

如何解析嵌套 JSON 结果中的动态 JSON 键?

如何使用 reactjs 和 graphql 在 gatsby 中映射嵌套数组