如何在反应组件状态下修改对象内的数组

Posted

技术标签:

【中文标题】如何在反应组件状态下修改对象内的数组【英文标题】:How to modify array within object in react component state 【发布时间】:2021-09-20 04:42:32 【问题描述】:

我的应用中有以下状态:

    const [activeChats, setActiveChats] = useState([
        
          id: 1,
          name: 'Luciana Gutierrez',
          role: 'HR Manager',
          avatar: avatar2,
          messages: [
            
              content: 'Hola Luciana! Tuviste alguna novedad?',
              received: false,
              date: '9:45 AM'
            ,
            
              content: 'Hola John! Todavía no...',
              received: true,
              date: '10:19 AM'
            ,
            
              content: 'Si tengo alguna otra novedad te comento. Gracias!',
              received: true,
              date: '10:20 AM'
            
          ]
        ,
        
          id: 2,
          name: 'Micaela Alvarez',
          role: 'Marketing Manager',
          avatar: avatar1,
          messages: [
            
              content: 'Hola John! Entre qué horarios podrías hoy tener la meeting?',
              received: true,
              date: '9:45 AM'
            ,
            
              content: 'Hola Micaela! Muy bien. Yo puedo de 10 a 17 hs.',
              received: false,
              date: '10:05 AM'
            ,
            
              content: 'Dale, agendé la meeting para hoy a las 14hs.',
              received: true,
              date: '10:15 AM'
            
          ]
        ,
        
          id: 3,
          name: 'Manuel Hoffman',
          role: 'Business Manager',
          avatar: avatar3,
          messages: [
            
              content: 'Gracias por la reunión de ayer, Manu, fue muy productiva!',
              received: false,
              date: '9:35 AM'
            ,
            
              content: 'Gracias a vos!',
              received: true,
              date: '9:37 AM'
            
          ]
        
      ])

我只想通过在每个对象的 messages 键中添加更多项目来修改它,让其余的状态保持原样。

例如,假设我向第一个对象添加了两条新消息。状态应如下所示:

const [activeChats, setActiveChats] = useState([
    
      id: 1,
      name: 'Luciana Gutierrez',
      role: 'HR Manager',
      avatar: avatar2,
      messages: [
        
          content: 'Hola Luciana! Tuviste alguna novedad?',
          received: false,
          date: '9:45 AM'
        ,
        
          content: 'Hola John! Todavía no...',
          received: true,
          date: '10:19 AM'
        ,
        
          content: 'Si tengo alguna otra novedad te comento. Gracias!',
          received: true,
          date: '10:20 AM'
        ,
        
          content: 'Example1',
          received: true,
          date: '10:21 AM'
        ,
        
          content: 'Example2',
          received: true,
          date: '10:22 AM'
        
      ]
    ,
    
      id: 2,
      name: 'Micaela Alvarez',
      role: 'Marketing Manager',
      avatar: avatar1,
      messages: [
        
          content: 'Hola John! Entre qué horarios podrías hoy tener la meeting?',
          received: true,
          date: '9:45 AM'
        ,
        
          content: 'Hola Micaela! Muy bien. Yo puedo de 10 a 17 hs.',
          received: false,
          date: '10:05 AM'
        ,
        
          content: 'Dale, agendé la meeting para hoy a las 14hs.',
          received: true,
          date: '10:15 AM'
        
      ]
    ,
    
      id: 3,
      name: 'Manuel Hoffman',
      role: 'Business Manager',
      avatar: avatar3,
      messages: [
        
          content: 'Gracias por la reunión de ayer, Manu, fue muy productiva!',
          received: false,
          date: '9:35 AM'
        ,
        
          content: 'Gracias a vos!',
          received: true,
          date: '9:37 AM'
        
      ]
    
  ])

我该怎么做? 我正在考虑扩展运算符,但我不确定如何将它与我拥有的嵌套一起使用。

【问题讨论】:

【参考方案1】:

您需要为setActiveStates 返回一个新数组,特别注意不要改变您正在更新的嵌套对象。一个长期的方法是 findIndex() 要更新的项目,然后使用这个索引到 spread slice()s 的数组之前和之后的问题,并检索和克隆项目本身和任何嵌套对象属性以返回副本。

const newMessages = [ content: 'new1', received: true, date: '10:21 AM' ,  content: 'new2', received: true, date: '10:22 AM' ];
const itemId = 1;

setActiveChats(prevState => 
  const index = prevState.findIndex(( id ) => id = itemId);
  const item = prevState[index];
  return [
    ...prevState.slice(0, index),
     ...item, messages: [...item.messages, ...newMessages] ,
    ...prevState.slice(index + 1)
  ];
);

【讨论】:

【参考方案2】:

用嵌套结构来做这件事有点乏味,但这样的事情应该可以工作:

    setActiveChats(
      activeChats.map((activeChat, idx) => 
        // Add to the first entry
        if (idx === 0) 
          return 
            ...activeChat,
            // assumes `newMessages` is an array of new messages
            messages: [...activeChat.messages, ...newMessages]
          ;
        
        return activeChat;
      )
    );

查看完整的工作示例here。

【讨论】:

以上是关于如何在反应组件状态下修改对象内的数组的主要内容,如果未能解决你的问题,请参考以下文章

如何正确更新反应钩子状态中的数组

如何在本机反应中基于数组内的图像uri渲染图像组件

如何在 Vue3 中使用数组访问反应对象内的数据?

如何将对象数组文件访问到反应组件中?

如何在标准化状态下使用结果数组以排序顺序呈现帖子

如何在反应中的对象数组中设置对象数组的状态