I'm working in an older codebase using React-Native 0.63 and I'm trying to add RNPickerSelect to the login page of an app. The app uses Redux for State management, I've created Types, Reducers, Selectors, Actions, and an Initial State for the Redux. After Importing the RNPickerSelect and the Picker appears on the screen, and allows interaction but whenever a value is selected the app crashes and gives no error.
Here's the LoginScreen.js Page
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Text, StatusBar, View, ScrollView, Platform, Image } from 'react-native'
import Config from 'react-native-config'
import { connect } from 'react-redux'
import { compose } from 'redux'
import { Colors } from '../Themes/'
import LoginActions, { LoginSelectors } from '../Redux/LoginRedux'
import RNPickerSelect from 'react-native-picker-select'
// Styles
import styles from './Styles/LoginScreenStyle'
import Logo from '../Components/Logo'
import LoginForm from '../Components/LoginForm'
import { withNavigation } from 'react-navigation'
import I18n from '../I18n/'
class LoginScreen extends Component {
static propTypes = {
userName: PropTypes.string,
password: PropTypes.string,
pickerValue: PropTypes.string,
updateUserName: PropTypes.func,
updatePassword: PropTypes.func,
updatePickerValue: PropTypes.func,
navigation: PropTypes.object,
doLogin: PropTypes.func,
siteUrl: PropTypes.string,
updateSiteUrl: PropTypes.func,
isLoggingIn: PropTypes.bool,
initialize: PropTypes.func
}
componentDidMount () {
const { userName, password, siteUrl, initialize } = this.props
if (!userName && !password && !siteUrl) {
initialize(Config.USER_NAME, Config.PASSWORD, Config.SITE_URL)
}
}
handlePressLogin = () => {
const { userName, password, siteUrl } = this.props
this.props.doLogin(userName, password, siteUrl)
}
render () {
const { userName, password, siteUrl, updateUserName, updatePassword, updateSiteUrl, isLoggingIn, updatePickerValue, pickerValue } = this.props
return (
<ScrollView contentContainerStyle={styles.mainScrollViewContainer}>
<View style={styles.contentArea}>
<View style={{backgroundColor: 'red'}}>
<StatusBar
barStyle={Platform.OS == 'ios' ? 'dark-content' : 'light-content'}
backgroundColor={Colors.primaryColor}
/>
</View>
<View style={styles.formViewContainer}>
<Logo size='small' />
<View style={styles.welcomeTextContainer}>
<Text style={styles.LogoText}>{I18n.t('loginPageWelcomeText')}</Text>
</View>
<RNPickerSelect
onValueChange={updatePickerValue}
items={[
{ label: 'Option 1', value: 'option1' },
{ label: 'Option 2', value: 'option2' },
{ label: 'Option 3', value: 'option3' },
]}
value={pickerValue}
/>
<LoginForm
userName={userName}
onUserNameChange={updateUserName}
password={password}
onPasswordChange={updatePassword}
siteUrl={siteUrl}
onSiteUrlChange={updateSiteUrl}
handlePressLogin={this.handlePressLogin}
isLogginIn={isLoggingIn}
/>
</View>
</View>
<View style={{marginBottom: 20}}><Image resizeMode='contain' style={{width: '100%'}} source={require('../Images/footer.jpeg')} /></View>
</ScrollView>
)
}
}
const mapStateToProps = (state) => {
return {
userName: LoginSelectors.getUserName(state),
password: LoginSelectors.getPassword(state),
pickerValue: LoginSelectors.getPickerValue(state),
siteUrl: LoginSelectors.getSiteUrl(state),
isLoggingIn: LoginSelectors.isLoggingIn(state),
}
}
const mapDispatchToProps = {
updateUserName: LoginActions.updateUserName,
updatePassword: LoginActions.updatePassword,
updateSiteUrl: LoginActions.updateSiteUrl,
updatePickerValue: LoginActions.updatePickerValue,
doLogin: LoginActions.loginRequest,
initialize: LoginActions.initialize
}
export default compose(
connect(mapStateToProps, mapDispatchToProps),
withNavigation
)(LoginScreen)
And here's my redux js
import { createReducer, createActions } from 'reduxsauce'
import { StartupTypes } from './StartupRedux'
import Immutable from 'seamless-immutable'
/* ------------- Types and Action Creators ------------- */
const { Types, Creators } = createActions({
initialize: ['userName', 'password', 'siteUrl'],
updateSiteUrl: ['siteUrl'],
updateUserName: ['userName'],
updatePassword: ['password'],
updatePickerValue: ['pickerValue'],
loginRequest: ['userName', 'password', 'siteUrl'],
loginSuccess: ['data'],
loginFailure: null,
logout: null
})
export const LoginTypes = Types
export default Creators
/* ------------- Initial State ------------- */
export const INITIAL_STATE = Immutable({
userName: '',
password: '',
siteUrl: '',
pickerValue: '',
accessToken: null,
displayName: '',
vendorId: null,
fetching: null,
payload: null,
error: null,
})
/* ------------- Selectors ------------- */
export const LoginSelectors = {
getData: state => state.data,
getSiteUrl: state => state.login.siteUrl,
getUserName: state => state.login.userName,
getPassword: state => state.login.password,
getPickerValue: state => state.login.pickerValue,
isLoggingIn: state => state.login.fetching,
getAccessToken: state => state.login.accessToken,
getDisplayName: state => state.login.displayName,
getVendorId: state => state.login.vendorId,
}
/* ------------- Reducers ------------- */
export const initialize = (state, { userName, password, siteUrl }) =>
state.merge({ userName, password, siteUrl })
export const request = (state, { data }) =>
state.merge({ fetching: true, data, payload: null })
export const success = (state, action) => {
const { data: { token: accessToken, store_name: displayName, store_id: vendorId } } = action
//console.log(vendorId)
return state.merge({ fetching: false, error: null, password: '', accessToken, displayName, vendorId })
}
export const updateUserName = (state, action) => {
const { userName } = action
return state.merge({ userName })
}
export const updatePassword = (state, action) => {
const { password } = action
return state.merge({ password })
}
export const updatePickerValue = (state, action) => {
const { pickerValue } = action
return state.merge({ pickerValue })
}
export const updateSiteUrl = (state, action) => {
const { siteUrl } = action
return state.merge({ siteUrl })
}
// Something went wrong somewhere.
export const failure = state =>
state.merge({ fetching: false, error: true, payload: null })
export const logout = state =>
INITIAL_STATE
export const onStartup = state =>
state.merge({ fetching: false })
/* ------------- Hookup Reducers To Types ------------- */
export const reducer = createReducer(INITIAL_STATE, {
[Types.LOGIN_REQUEST]: request,
[Types.LOGIN_SUCCESS]: success,
[Types.LOGIN_FAILURE]: failure,
[Types.UPDATE_USER_NAME]: updateUserName,
[Types.UPDATE_PASSWORD]: updatePassword,
[Types.UPDATE_SITE_URL]: updateSiteUrl,
[Types.UPDATE_PICKER_VALUE]: updatePickerValue,
[Types.LOGOUT]: logout,
[Types.INITIALIZE]: initialize,
[StartupTypes.STARTUP]: onStartup,
})
I've tried different pickers but RNPickerSelect seems to be the only one that even starts to display when I use it.
I've also tried putting it a level lower in the <LoginForm> component but for the sake of trying to make it easier on myself I've moved it up into LoginScreen instead.
I'm very new to React/React Native as well as Redux so I apologize if this is a bit of a noob question. Any help is greatly appreciated!