Как обновить массив неизменным образом - PullRequest
0 голосов
/ 06 сентября 2018


Truble! Помогите, пожалуйста. Я буду так признателен!
В этом объекте я должен неизменным образом обновлять только массив комментариев (все это только фиктивные данные, не имеет значения):

const initialState = {
  news: [
    {
      id: 1,
      text: 'Hello!',
      createdBy: '',
      comments: [{ id: 0, author: 0, commentText: 0 }]
    },
    {
      id: 2,
      text: 'TEST',
      createdBy: '',
      comments: [{ id: 11, author: 11, commentText: 11 }, { id: 12, author: 12, commentText: 12 }]
    },
    {
      id: 3,
      text: 'TEXT:)',
      createdBy: '',
      comments: []
    }
  ]
}

И это действительно сложно ... Я перепробовал много вариантов, но безуспешно ... (
Мой редуктор:

const newsReducer = (state = initialState, action) => {
  switch (action.type) {
    case actionTypes.ADD_COMMENT:
      const { id, author, commentText, newsItemId } = action.payload;
      // which element to update
      const index = state.news.findIndex(item => item.id === newsItemId);
      return {
        ...state,
        news: [
          ...state.news
          [index] = {
            ...state.news[index],
            comments: state.news[index].comments.concat({ id, author, commentText })
          }
        ]
      }
    default:
      return state;
  }
}

Буду благодарен за любые советы

1 Ответ

0 голосов
/ 06 сентября 2018

Распространение синтаксиса - один из способов решения этой проблемы, другой способ - использование линз, которые можно найти в таких библиотеках, как Ramda .

Линзы позволяют вам «увеличивать» определенную часть структуры данных и обновлять значение, возвращая новую версию всей структуры данных.

const R = require('ramda')
const a = {a:'foo', b:[1, 2, 3]}
const b = R.over(R.lensPath(['b']), nums => nums.concat(4), a)
console.log(b) //-> {a:'foo', b:[1, 2, 3, 4]}

Используя линзы, ваш редуктор можно выразить как:

const R = require('ramda')
const newsReducer = (state = initialState, action) => {
  switch (action.type) {
    case actionTypes.ADD_COMMENT:
      const { id, author, commentText, newsItemId } = action.payload
      const i = state.news.findIndex(item => item.id === newsItemId)
      return R.over(
        R.lensPath(['news', i, 'comments']),
        comments => comments.concat({ id, author, commentText }),
        state
      )
      default:
        return state;
  }
}
...