Начальное состояние данных массива не определено в редюсере

Я хотел бы сохранить данные объекта внутри состояния массива. Но когда я пытаюсь вызвать действие в редукторе, INITIAL_STATE.highlightedVerse всегда приводит к undefined, когда я пытаюсь использовать console.log(). Это должен быть пустой массив, а не неопределенный.

Это зависимости, которые я использовал в package.json Expo v32.0.0, React v16.5.0, Redux v4.0.1, React Redux v5.1.1, Redux Persist v.5.10.0.

Это код, который я написал:

import {
  ADD_BIBLE_VERSE_HIGHLIGHT,
  REMOVE_BIBLE_VERSE_HIGHLIGHT,
} from 'ndc-ministry/redux/actions/types'

const INITIAL_STATE = {
  highlightedVerse: [],
}

const reducer = (state = INITIAL_STATE, action) => {

  switch (action.type) {
    case ADD_BIBLE_VERSE_HIGHLIGHT:
      const currentHighlightedVerse = state.highlightedVerse
      if(currentHighlightedVerse.length > 0){
        currentHighlightedVerse.forEach(obj => {
          if(action.payload.bookIndex == obj.bookIndex 
            && action.payload.chapterIndex == obj.chapterIndex 
            && action.payload.verseIndex == obj.verseIndex
          ) {
            return {...state}
          }
        })
      }

      return {
        ...state,
        highlightedVerse: [...state.highlightedVerse, action.payload]
      }


    case REMOVE_BIBLE_VERSE_HIGHLIGHT:
      const deletedHighlightVerse = state.highlightedVerse.filter(obj => JSON.stringify(action.payload) != JSON.stringify(obj))
      return {
        ...state,
        highlightedVerse: deletedHighlightVerse
      }

    default:
      return state

  }
}

export default reducer

В режиме разработки работает нормально. Но когда я обновил его до рабочей версии APK/IPA, он всегда возвращает значение undefined, и я понятия не имею, как это сделать. Я уже пытался искать два дня, но так и не смог понять, почему.

Спасибо за чтение этого вопроса, и я надеюсь, что кто-то может помочь мне в этом :)


person Kevin Hobert    schedule 16.08.2019    source источник
comment
Вам нужно показать, как вы подключаете свой компонент, свои диспетчеры действий и как настроен ваш корневой редуктор.   -  person Clarity    schedule 16.08.2019
comment
Звучит как что-то, что не так просто решить. Как насчет его явной инициализации при запуске приложения?   -  person Yossi    schedule 16.08.2019
comment
Можете ли вы показать нам код, в котором вы создаете магазин?   -  person Domino987    schedule 16.08.2019


Ответы (3)


Я думаю, у вас проблема с функцией mapStateToProps. Если вы измените его, чтобы иметь объект состояния (BibleReducer) без деструктурирования присваивания в списке параметров функции, тогда у вас будет необходимое значение в свойстве hightlightedVerse.

Вы можете проверить значение путем отладки или выполнения console.log(BibleReducer), чтобы проверить, где и как значение вашей переменной отображается в коде.

Оригинальный - из вашего кода с деструктурированием значение не определено:

function mapStateToProps({BibleReducer}) {
  console.log(BibleReducer);

  return {
    highlightedVerse: BibleReducer.highlightedVerse,
  }
}

Я думаю, рабочий - у вас должен быть объект состояния:

function mapStateToProps(BibleReducer) {
  console.log(BibleReducer);

  return {
    highlightedVerse: BibleReducer.highlightedVerse,
  }
}

Дополнительную информацию о присваивании деструктуризации читайте здесь.

Синтаксис деструктурирующего присваивания — это выражение JavaScript, позволяющее распаковывать значения из массивов или свойства объектов в отдельные переменные.

При деструктурировании вы ссылаетесь на свойство state.BibleReducer.highlightedVerse, и я думаю, именно поэтому значение отображается как неопределенное.

Дайте мне знать, если это работает или нет, мы можем подумать дальше, если это необходимо.

ОБНОВЛЕНИЕ: если вы хотите использовать все еще назначение деструктурирования, вы можете использовать следующее решение, чтобы использовать только значение массива highlightedVerse:

function mapStateToProps({highlightedVerse}) {
   console.log(highlightedVerse);

   return {
      highlightedVerse: highlightedVerse,
   }
}

Спасибо @Clarity за идею!

person norbitrial    schedule 16.08.2019
comment
Это может быть просто const mapStateToProps = (state) => ( { highlightedVerse: state.highlightedVerse, }) - person Clarity; 16.08.2019
comment
Я не думаю, что это проблема, потому что я использовал CombineReducer, и он нормально работает с другими файлами. Я уже console.log все до редуктора. Я видел, что action.payload работает нормально. Но редуктор печатает undefined, когда я console.log(state.highlightedVerse) - person Kevin Hobert; 16.08.2019
comment
Какое значение вы имеете, когда ведете журнал, например console.log(state); Только? - person norbitrial; 16.08.2019
comment
@norbitrial печатает Object { selectedVerse: Array [], notesVerse: Array [], selectedBookIndex: 0, selectedChapterIndex: 0, selectedVerseIndex: 0, } - person Kevin Hobert; 20.08.2019

Спасибо @Clarity @Yossi @Domino987

Вот мой магазин/index.js

import { AsyncStorage } from 'react-native'
import storage from 'redux-persist/lib/storage'
import { createStore } from 'redux'
import { persistStore, persistReducer } from 'redux-persist'
import reducers from 'ndc-ministry/redux/reducers'

const persistConfig = {
  key: 'root',
  storage: AsyncStorage
}

const persistedReducer = persistReducer(persistConfig, reducers)

export const store = createStore(
  persistedReducer,
)

export const persistor = persistStore(store)

Странно то, что каждое состояние в моем редуксе хранится и сохраняется ХОРОШО, за исключением случаев, когда состояние является массивом. Вот как я отправляю свое действие в компоненте React

 import { addBibleVerseHighlight } from 'project-name/redux/actions'
    class BibleScreen extends Component {

addHighlight = () => {
    this.state.selectedVersesIndex.map((value) => {
      const verseData = {
        bookIndex: this.props.selectedBookIndex,
        chapterIndex: this.props.selectedChapterIndex,
        verseIndex: value,
      }

        this.props.addBibleVerseHighlight(verseData)

    })
  }

    render() { ... }
    }


    function mapStateToProps({BibleReducer}) {
      return {
        highlightedVerse: BibleReducer.highlightedVerse,
      }
    }

    const mapDispatchToProps = {
      addBibleVerseHighlight,
      removeBibleVerseHighlight,
    }

    export default connect(mapStateToProps, mapDispatchToProps)(BibleScreen)
person Kevin Hobert    schedule 16.08.2019
comment
Вы бы переместили этот код в свой вопрос, отредактировав его. - person Clarity; 16.08.2019

Я бы сказал, упростите свой редуктор и удалите поле highlightedVerse. А затем относитесь к своему состоянию как к массиву, а не к массиву объектов.

Так что измените с {} на [], где это применимо.

Например (и без тестирования):

import {
  ADD_BIBLE_VERSE_HIGHLIGHT,
  REMOVE_BIBLE_VERSE_HIGHLIGHT,
} from 'ndc-ministry/redux/actions/types'

const INITIAL_STATE = [];

const reducer = (state = INITIAL_STATE, action) => {

  switch (action.type) {
    case ADD_BIBLE_VERSE_HIGHLIGHT:
      const currentHighlightedVerse = [...state];

      if(currentHighlightedVerse.length > 0){
        currentHighlightedVerse.forEach(obj => {
          if(action.payload.bookIndex == obj.bookIndex 
            && action.payload.chapterIndex == obj.chapterIndex 
            && action.payload.verseIndex == obj.verseIndex
          ) {
            return state;
          }
        })
      }

      return [...state, action.payload];


    case REMOVE_BIBLE_VERSE_HIGHLIGHT:
      const deletedHighlightVerse = state.filter(obj => JSON.stringify(action.payload) != JSON.stringify(obj))

      return deletedHighlightVerse;

    default:
      return state

  }
}

export default reducer

Таким образом, в вашем InitialState для вашего магазина... ваше поле highlightedVerse может быть пустым массивом, и вы можете установить этот редуктор в качестве редуктора для этого поля.

Удачи.

person niiapa    schedule 16.08.2019
comment
Привет! Спасибо за ответ. На самом деле в моем реальном случае INITIAL_STATE имеет много полей. Не только один. Я просто упрощаю свой код выше, потому что это слишком много, чтобы показать все. И я понял, что проблема в INITIAL_STATE, где значением по умолчанию является массив. Другие INITIAL_STATE не имеют проблем - person Kevin Hobert; 20.08.2019