【问题标题】:Initial State of Array data is undefined within Reducer在 Reducer 中未定义数组数据的初始状态
【发布时间】:2019-08-16 09:25:14
【问题描述】:

我想将对象数据保存在我的数组状态中。 但是当我尝试在 reducer 中调用一个动作时,当我尝试 console.log() 时,INITIAL_STATE.highlightedVerse 总是导致 undefined。它应该是一个空数组,而不是未定义的。

这些是我在 package.json 中使用的依赖项 世博会 v32.0.0, 反应 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 时,它总是返回未定义,我不知道如何。我已经尝试搜索了两天,但仍然不明白为什么。

感谢您阅读此问题,我希望有人可以帮助我:)

【问题讨论】:

  • 你需要展示你如何连接你的组件、你的动作调度器以及你的根减速器是如何设置的。
  • 听起来好像不太容易解决。启动应用时显式初始化如何?
  • 你能告诉我们你创建商店的代码吗?

标签: reactjs react-native redux react-redux redux-persist


【解决方案1】:

我认为您的 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,
  }
}

请进一步阅读解构赋值here

解构赋值语法是一种 JavaScript 表达式,它可以将数组中的值或对象中的属性解包到不同的变量中。

通过解构,您将引用state.BibleReducer.highlightedVerse 属性,我认为这就是该值显示为未定义的原因。

让我知道这是否有效,如果需要,我们可以进一步考虑。

更新: 如果您想使用仍然解构分配,那么您可以选择以下解决方案以仅使用 highlightedVerse 数组值:

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

   return {
      highlightedVerse: highlightedVerse,
   }
}

感谢@Clarity 的创意!

【讨论】:

  • 可以是const mapStateToProps = (state) => ( { highlightedVerse: state.highlightedVerse, })
  • 我不认为这是问题所在,因为我使用了combinedReducer,它与其他文件正常工作。我已经 console.log 一切都到了减速器。我看到 action.payload 工作正常。但是当我 console.log(state.highlightedVerse) 时,reducer 打印 undefined
  • 当你做一个像 console.log(state); 这样的日志记录时你有什么价值;只有?
  • @norbitrial 它打印 Object { "highlightedVerse": Array [], "notedVerse": Array [], "selectedBookIndex": 0, "selectedChapterIndex": 0, "selectedVerseIndex": 0, }
【解决方案2】:

谢谢@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)

奇怪的是,我的 redux 中的每个状态都存储和持久化得很好,除非状态是一个数组。这就是我在 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)

【讨论】:

  • 您可以通过编辑将此代码移至您的问题。
【解决方案3】:

我会说简化你的减速器并删除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

这种方式在您的商店的初始状态中...您的 highlightedVerse 字段可以是一个空数组,您可以将此减速器设置为该字段的减速器。

祝你好运。

【讨论】:

  • 您好!感谢您回答这个问题。实际上在我的真实案例中, INITIAL_STATE 有很多字段。不止一个。我只是简化了上面的代码,因为显示所有内容太多了。我意识到问题出在默认值为数组的 INITIAL_STATE 中。其他INITIAL_STATE没有问题
猜你喜欢
  • 2017-02-07
  • 1970-01-01
  • 2021-02-09
  • 1970-01-01
  • 2019-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-04
相关资源
最近更新 更多