首页 > 解决方案 > 反应原生 redux 传奇 TypeError

问题描述

首先,我为长篇道歉,我尽量缩短。我试图通过 saga 调度一个动作,但我收到TypeError: resultFunc.apply is not a function error。

该函数在 Application reducer 中设置了两个变量:

商店/应用程序/Actions.js

const { Types, Creators } = createActions({
  // Set language for the app from user
  firstTimer: ['language'],
  setDeviceLanguage: ['language'],
})

export const AppTypes = Types
export default Creators

商店/应用程序/Reducers.js

import { INITIAL_STATE } from './InitialState'
import { createReducer } from 'reduxsauce'
import { AppTypes } from './Actions'

export const firstTimer = (state, { language }) => ({
  ...state,
  isFristTimer: false,
  appLanguage: language,
})
export const reducer = createReducer(INITIAL_STATE, {
  [AppTypes.FIRST_TIMER]: firstTimer,
  [AppTypes.SET_DEVICE_LANGUAGE]: setDeviceLanguage,
})

商店/应用程序/Selector.js

import { createSelector } from 'reselect'

const isFristTimer = (state) => state.isFristTimer
const language = (state) => state.language

export const getFirstTimer = createSelector([isFristTimer, language])

Sagas/AppSaga.js

import { put, select } from 'redux-saga/effects'
import * as Selectors from 'App/Stores/App/Selectors'

export function* firstTimer() {
  const whereTo = yield select(Selectors.getFirstTimer)
  const language = yield select(Selectors.language)
  Reactotron.log('getFirstTimer value', whereTo)
  Reactotron.log('language value', language)
  // When those operations are finished we redirect to the main screen
}

注意:选择器中的两个变量不会登录 Reactotron!!。

萨加斯/index.js

import { takeLatest, all } from 'redux-saga/effects'
import { firstTimer } from './AppSaga'
import { AppTypes } from 'App/Stores/App/Actions'

export default function* root() {
  yield all([
    // Call `firstTimer()` when a `FIRST_TIMER` action is triggered
    takeLatest(AppTypes.FIRST_TIMER, firstTimer),
  ])

在我的rootScreen.js中,我根据上面提到的firstTime变量有条件地渲染

  componentDidMount() {
    Reactotron.log('our state : ' + this.props.app)
  }

  _setLanguage(language) {
    this.props.setFirstTimer(language)
  }

  render() {
    const { isFristTimer } = this.props.app
    if (isFristTimer) {
      return (
        <View style={Helpers.fill}>
          <ImageBackground source={Images.firstTimerBg} style={Helpers.fullSize}>
            <View
              style={[
                Style.buttonWrapper,
                Helpers.mainCenter,
                Helpers.mainSpaceBetween,
                Helpers.row,
                Metrics.mediumHorizontalMargin,
              ]}
            >
              <TouchableOpacity
                onPress={() => this._setLanguage('en')}
                style={[Style.buttonContainer, Helpers.center]}
              >
                <Text style={Fonts.normal}>{Words.english}</Text>
              </TouchableOpacity>
              <TouchableOpacity
                onPress={() => this._setLanguage('ar')}
                style={[Style.buttonContainer, Helpers.center]}
              >
                <Text style={Fonts.normal}>{Words.arabic}</Text>
              </TouchableOpacity>
            </View>
          </ImageBackground>
        </View>
      )
    }
    return (
      <View style={Helpers.fill}>
        <AppNavigator
          // Initialize the NavigationService (see https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html)
          ref={(navigatorRef) => {
            NavigationService.setTopLevelNavigator(navigatorRef)
          }}
        />
      </View>
    )
  }
}

最终结果:

在此处输入图像描述

如果我解除错误,则应用程序不再呈现第一个块,而是呈现 AppNavigator

标签: javascriptreact-nativereduxreact-reduxredux-saga

解决方案


问题在于getFirstTimer选择器 - 第二个参数createSelector应该是resultFunc(您在错误中看到引用的)它获取它所依赖的其他选择器的结果并返回一个值。请参阅https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc。更新getFirstTimer应该可以解决问题:

import { createSelector } from 'reselect'

const isFristTimer = (state) => state.isFristTimer
const language = (state) => state.language

export const getFirstTimer = createSelector(
  [isFristTimer, language],
  // here is where the result func is added to the selector definition
  (isFristTimer, language) => ({
    isFristTimer,
    language,
  })
)

推荐阅读