Redux хранит неизменяемый шаблон для вложенных данных в массиве?

#javascript #arrays #json #reactjs #redux

#javascript #массивы #json #reactjs #redux

Вопрос:

У меня есть простой массив данных JSON, который выглядит следующим образом (он такой же в моем хранилище Redux, и я храню его под properties ):

 [
  {
    "id": "room",
    "name": "Room",
    "description": "Just a room",
    "foo": "bar",
  },
  {
    "id": "apartment",
    "name": "Apartment",
    "description": "just an apartment",
    "foo": "bar",
  }
]
  

Это должен быть массив, потому что я сопоставляю его:

 {properties.map(property => 
  <Property 
    id={property.id} 
    name={property.name} 
    description={property.description} 
    foo={property.foo}
 />)}
  

Таким образом, у меня есть два свойства, отображаемые в моем приложении.

Вопрос в том, как мне обновить "foo" в Redux?

Этот мой редуктор в настоящее время написан в соответствии с документами:

 case 'UPDATE_FOO':
  return {
    ...state, 
    properties: {
      ...state.properties,
      [action.id]: {
      ...state.properties[action.id],
      foo: action.fooData,
    }
  }
}
  

Конечно, он выдает TypeError: Cannot read property 'room' of undefined , потому что я пытаюсь получить доступ state.properties["room"] , а этого не существует.

Я думал о том, чтобы изменить форму моего хранилища JSON и Redux, но как только я меняю его на именованные объекты, я не могу сопоставить его…

Спасибо!

Ответ №1:

Измените свое хранилище на объект и сгенерируйте массив, когда вам нужно его отобразить, преобразовав его в массив, используя Object.values() :

 {Object.values(properties).map(property => (
  <Property key={property.id} {...property} />
)}
  

Если порядок может измениться (например, сортировка), вам необходимо иметь другой массив с идентификаторами для хранения порядка (см. redux normalized state).:

 {
  properties: {
    room: {
      "id": "room",
      "name": "Room",
      "description": "Just a room",
      "foo": "bar",
    },
    apartment: {
      "id": "apartment",
      "name": "Apartment",
      "description": "just an apartment",
      "foo": "bar",
    }
  }
}

{
  properties: {
    room: {
      "id": "room",
      "name": "Room",
      "description": "Just a room",
      "foo": "bar",
    },
    apartment: {
      "id": "apartment",
      "name": "Apartment",
      "description": "just an apartment",
      "foo": "bar",
    }
  },
  order: ['apartment', 'room']
}
    
{order.map(id => (
  <Property key={id} {...properties[id]} />
)}
  

Комментарии:

1. Может быть, стоит указать, что рендеринг Property может быть сокращен до Object.values(properties).map(property => <Property key={property.id} {...property}/>)

2. Мне очень нравится ваш ответ, но настройка хранилища с помощью JSON в формате, подобном этому: const initialState = { myJsonData} закончится тем, что state.properties.properties и это добавит еще один уровень к моему редуктору, я прав? 🙁

3. Нет — это просто state.properties . Массив properties заменяется объектом properties .

4. @OriDrori хм, тогда я, должно быть, делаю что-то не так, но я думаю, что «свойства» перетаскиваются сюда из файла JSON: imgur.com/a/FECwFCq . Не имеет значения, инициализирую ли я хранилище с const initialState = {properties: myJsonData} помощью or const initialState = {myJsonData} , я всегда получаю его в два раза: [

5. Вам нужно будет нормализовать JSON при его вставке, что означает, что вам нужно будет повторить его и создать форму состояния в редукторе.

Ответ №2:

Если вы хотите обновить хранилище, используя только идентификатор. Вы можете найти один элемент (который вы пытаетесь отредактировать) в массиве свойств, используя идентификатор, а затем обновить его:

     case 'UPDATE_FOO':
        const newProperties = state.properties.map(property => {
            if(property.id === action.id) {
                return { ...property, foo: action.fooData}
            }
            return property;
        })
        return {
            ...state,
            properties: newProperties
        }
     }
  

Комментарии:

1. Это здорово, но так сложно читать и понимать: (Я думаю, я должен пойти с immer, по крайней мере, тогда? Это плоский JSON, и все еще обновление prop выглядит так безумно.