反应本机 redux 传奇 TypeError
React native redux saga TypeError
首先,很抱歉post,我尽量缩短了。
我正在尝试通过 saga 发送一个动作,但我收到 TypeError: resultFunc.apply is not a function 错误。
该函数在 Application reducer 中设置了两个变量:
- isFirstTimer:
false
- 应用程序语言:
en
Store/App/Actions.js
const { Types, Creators } = createActions({
// Set language for the app from user
firstTimer: ['language'],
setDeviceLanguage: ['language'],
})
export const AppTypes = Types
export default Creators
Store/App/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,
})
Store/App/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!!.
Sagas/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>
)
}
}
The end result :
如果我消除错误,应用程序将不再呈现第一个块,而是呈现 AppNavigator
问题出在 getFirstTimer
选择器上 - createSelector
的第二个参数应该是 resultFunc
(您在错误中看到的引用),它接受其他选择器的结果它取决于 returns 一个值。参见 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,
})
)
首先,很抱歉post,我尽量缩短了。 我正在尝试通过 saga 发送一个动作,但我收到 TypeError: resultFunc.apply is not a function 错误。
该函数在 Application reducer 中设置了两个变量:
- isFirstTimer:
false
- 应用程序语言:
en
Store/App/Actions.js
const { Types, Creators } = createActions({
// Set language for the app from user
firstTimer: ['language'],
setDeviceLanguage: ['language'],
})
export const AppTypes = Types
export default Creators
Store/App/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,
})
Store/App/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!!.
Sagas/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>
)
}
}
The end result :
如果我消除错误,应用程序将不再呈现第一个块,而是呈现 AppNavigator
问题出在 getFirstTimer
选择器上 - createSelector
的第二个参数应该是 resultFunc
(您在错误中看到的引用),它接受其他选择器的结果它取决于 returns 一个值。参见 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,
})
)