【发布时间】:2021-01-03 13:47:53
【问题描述】:
我正在将我的 react 本机应用程序从 61.5 更新到 63.2,现在在日志中出现以下错误,我无法弄清楚我做错了什么。
错误信息 警告:函数作为 React 子级无效。如果您返回一个组件而不是从渲染中返回,则可能会发生这种情况。或者,也许您打算调用这个函数而不是返回它。
in Unknown (at Login/index.js:191)
in Login (created by ConnectFunction)
in ConnectFunction (created by SceneView)
in SceneView (created by CardContainer)
in RCTView (at View.js:34)
in View (created by CardContainer)
in RCTView (at View.js:34)
in View (created by CardContainer)
in RCTView (at View.js:34)
in View (created by ForwardRef(CardSheet))
in ForwardRef(CardSheet) (created by Card)
in RCTView (at View.js:34)
in View (at createAnimatedComponent.js:165)
in AnimatedComponent (at createAnimatedComponent.js:215)
in ForwardRef(AnimatedComponentWrapper) (created by PanGestureHandler)
in PanGestureHandler (created by PanGestureHandler)
in PanGestureHandler (created by Card)
in RCTView (at View.js:34)
in View (at createAnimatedComponent.js:165)
in AnimatedComponent (at createAnimatedComponent.js:215)
in ForwardRef(AnimatedComponentWrapper) (created by Card)
in RCTView (at View.js:34)
in View (created by Card)
in Card (created by CardContainer)
in CardContainer (created by CardStack)
in RCTView (at View.js:34)
in View (created by MaybeScreen)
in MaybeScreen (created by CardStack)
in RCTView (at View.js:34)
in View (created by MaybeScreenContainer)
in MaybeScreenContainer (created by CardStack)
in CardStack (created by KeyboardManager)
in KeyboardManager (created by Context.Consumer)
in RNCSafeAreaView (at src/index.tsx:28)
in SafeAreaProvider (created by Context.Consumer)
in SafeAreaProviderCompat (created by StackView)
in RCTView (at View.js:34)
in View (created by StackView)
in StackView (created by StackView)
in StackView
in Unknown (created by Navigator)
in Navigator (created by SceneView)
in SceneView (created by SwitchView)
in SwitchView (created by Navigator)
in Navigator (created by NavigationContainer)
in NavigationContainer (at App.js:57)
in RCTView (at View.js:34)
in View (at App.js:52)
in PersistGate (at App.js:51)
in Provider (at App.js:50)
in App (at renderApplication.js:45)
in RCTView (at View.js:34)
in View (at AppContainer.js:106)
in RCTView (at View.js:34)
in View (at AppContainer.js:132)
in AppContainer (at renderApplication.js:39)
下面是我认为是问题的“登录”屏幕中的代码。
import React, { Component } from 'react'
import {
Alert,
View,
StyleSheet,
Image,
Platform,
Keyboard,
TouchableWithoutFeedback,
TouchableOpacity,
PermissionsAndroid
} from 'react-native'
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'
import { connect } from 'react-redux'
import { Formik } from 'formik'
import _ from 'lodash'
import { ButtonGroup } from 'react-native-elements'
import { FormInput, Text, Button } from 'components'
import * as actions from 'redux/actions'
import { styles as appStyles } from 'common/styles'
import { w, m, h } from 'common/helpers'
import images from 'images'
import apiErrorsById from 'common/apiErrorsById'
import config from 'common/config'
import TosModal from './TosModal'
import InputModal from './InputModal'
import geolocation from '@react-native-community/geolocation'
import { isIphoneX } from 'react-native-iphone-x-helper'
const { colors } = appStyles
const buttons = ['Yes', 'No']
class Login extends Component {
page = 'login'
state = {
selectedIndex: this.props.state.settings.saveUsername === true ? 0 : 1,
tosModalVisible: false,
inputModalVisible: false,
inputValue: 'http://'
}
requestLocationPermissionAndroid = async () => {
try {
await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: 'Location Access Required',
message: 'This App needs to Access your location'
}
)
} catch (error) {
// console.log('location permission error', error);
}
}
componentDidMount() {
if (Platform.OS === 'ios') {
geolocation.requestAuthorization()
} else {
this.requestLocationPermissionAndroid()
}
if (!this.props.state.settings.TOSAccepted) {
this.setState({ tosModalVisible: true })
}
const {
settingsfileurl,
enableautosettingsupdate
} = this.props.state.settings.general
if (enableautosettingsupdate) {
this.props.getSettingsFromUrl(settingsfileurl, false)
}
}
onSubmitEditing = (i, props) => {
const nextInput = this['input' + ++i]
nextInput ? nextInput.focus() : console.log('dont submitt') // this.onLoginPress(props)
}
componentDidUpdate(nextProps) {
const { settingsdownloaded } = nextProps.state.settings
if (settingsdownloaded && this.state.inputModalVisible) {
this.setState({ inputModalVisible: false }), () => {}
}
}
rememberUserName = () => {
const storeName = 'settings'
const shouldRemember = this.state.selectedIndex == 0
const { unitName, userName, password } = this.formikProps.values
const newValues = [
{ prop: 'unitName', value: unitName },
{ prop: 'userName', value: userName },
{ prop: 'password', value: password },
{ prop: 'saveUsername', value: shouldRemember ? true : false }
]
newValues.forEach(item => {
this.props.valueChange({
storeName,
prop: item.prop,
value: item.value
})
})
}
gatherLoginData = () => {
const { values } = this.formikProps
const loginData = {
...values,
navigation: this.props.navigation
}
return loginData
}
onLoginPress = async () => {
this.rememberUserName()
const { password, unitName, userName } = this.formikProps.values;
if (!password || !userName) {
Alert.alert('Username, and Password are required.', '', [{ text: 'OK' }])
} else {
this.props.loginAction(this.gatherLoginData())
}
// ==this.props.navigation.navigate('Test');
}
onBtnGrpPress = selectedIndex => {
this.setState({ selectedIndex })
}
onTosAcceptPress = () => {
this.setState({ tosModalVisible: false })
this.props.valueChange({
storeName: 'settings',
prop: 'TOSAccepted',
value: true
})
}
modalClose = () => {
this.setState({ inputModalVisible: false })
}
onDownloadSettingsPress = () => {
// this.modalClose();
Keyboard.dismiss()
this.props.getSettingsFromUrl(this.state.inputValue)
}
render() {
const { selectedIndex } = this.state
const {
settings,
app: {
errorMessages: { login: errorId }
}
} = this.props.state
const { userName, unitName, saveUsername, isDayTime } = settings
const {
vehiclelogin,
employee1login,
employee2login,
mileagelogin
} = settings.general
const inputs1 = [
{ name: 'unitName', label: 'Unit', placeholder: 'Enter a Unit', visible: true },
{ name: 'userName', label: 'Username', placeholder: 'Enter a Username', visible: true },
{
name: 'password',
label: 'Password',
placeholder: 'Enter a Password',
secureTextEntry: true,
visible: true
},
{ name: 'Mileage', label: 'Mileage', placeholder: 'Enter a Mileage', visible: (mileagelogin || mileagelogin === undefined) },
]
const inputs2 = [
{ name: 'Vehicle', label: 'Vehicle', placeholder: 'Enter a Vehicle', visible: (vehiclelogin || vehiclelogin === undefined) },
{ name: 'EmployeeNumber1', label: 'Employee #1', placeholder: 'Enter Employee #1', visible: (employee1login || employee1login === undefined) },
{ name: 'EmployeeNumber2', label: 'Employee #2', placeholder: 'Enter Employee #2', visible: (employee2login || employee2login === undefined) },
]
// console.log(this.props.state);
return (
<KeyboardAwareScrollView
contentContainerStyle={[
styles.container,
{ backgroundColor: isDayTime ? colors.white : colors.black }
]}
keyboardShouldPersistTaps='always'
>
<View
style={{
width: m(200),
height: m(200),
alignSelf: 'center',
marginVertical: h(5)
}}
>
<TouchableWithoutFeedback
onPress={() =>
Alert.alert(
'Version: ' +
config.appVersion +
`\nRelease Date: ${config.releaseDate}`
)
}
>
<Image
style={{ height: null, width: null, flex: 1 }}
source={images.logo}
/>
</TouchableWithoutFeedback>
</View>
<View style={styles.headerContainer}>
<Text center bold normal>
Enter the information below to login to EnRoute Mobile
</Text>
</View>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginHorizontal: h(20)
}}
>
<Text small>Remember Username | Unit Login?</Text>
<ButtonGroup
buttons={buttons}
selectedButtonStyle={{ backgroundColor: colors.black }}
selectedTextStyle={{ color: colors.white }}
selectedIndex={selectedIndex}
containerBorderRadius={5}
onPress={this.onBtnGrpPress}
textStyle={{ paddingVertical: h(3), fontSize: m(12) }}
containerStyle={{ width: '30%', height: h(30) }}
/>
</View>
<Text normal bold center style={{ marginVertical: h(10) }}>
All Fields Are Case Sensitive
</Text>
<Formik
onSubmit={values => console.log('values:', values)}
initialValues={
saveUsername
? { userName, unitName }
: { userName: '', unitName: '' }
}
>
{props => {
this.formikProps = props
return (
<View>
<View style={{ flexDirection: 'row' }}>
<View style={{ flex: 1, marginHorizontal: 2 }}>
{inputs1.map((item, i) => {
if (!item.visible) {
return null
}
return (
<FormInput
key={item.name}
{...item}
{...props}
lastElement={i === inputs1.length - 1}
onSubmitEditing={() =>
this.onSubmitEditing(i, props)
}
refInput={el =>
(this['input' + i] = el)
}
returnKeyType="next"
/>
)})}
</View>
<View style={{ flex: 1, marginHorizontal: 2 }}>
{inputs2.map((item, i) => {
if (!item.visible) {
return null
}
return (
<FormInput
key={item.name}
{...item}
{...props}
lastElement={i === inputs2.length - 1}
onSubmitEditing={() =>
this.onSubmitEditing(inputs1.length + i, props)
}
refInput={el =>
(this['input' + (4 + i)] = el)
}
returnKeyType="next"
/>
)})}
</View>
</View>
<Button
label='Login'
labelStyle={styles.buttonText}
buttonStyle={styles.button}
onPress={() => this.onLoginPress(props)}
/>
</View>
)
}}
</Formik>
<View style={{ marginTop: h(5) }}>
{
<Text red mini center>
{errorId && errorId.toString()}
</Text>
}
</View>
<Button
size={40}
containerViewStyle={styles.settingsButton}
image={'settings'}
onPress={() =>
this.props.navigation.navigate({
routeName: 'SettingsStack',
key: 'settings',
params: { prevStack: 'Login' }
})
}
/>
<TosModal
isVisible={this.state.tosModalVisible}
navigation={this.props.navigation}
onAcceptPress={this.onTosAcceptPress}
onModalHide={() =>
this.setState({ inputModalVisible: true })
}
/>
<InputModal
isVisible={this.state.inputModalVisible}
value={this.state.inputValue}
onChangeText={value => this.setState({ inputValue: value })}
onPress={this.onDownloadSettingsPress}
modalClose={this.modalClose}
/>
</KeyboardAwareScrollView>
)
}
}
export default connect(state => ({ state }), actions)(Login)
let paddingTop = 0
if (Platform.OS === 'ios') {
paddingTop = 20
}
if (isIphoneX()) {
paddingTop = 40
}
const styles = StyleSheet.create({
container: {
paddingTop,
flexGrow: 1,
backgroundColor: colors.white,
paddingHorizontal: w(20),
paddingBottom: h(20)
},
headerContainer: {
backgroundColor: colors.darkGray,
padding: w(5),
borderRadius: w(5),
marginVertical: h(5)
},
button: {
width: '80%',
borderRadius: w(5),
backgroundColor: colors.lightGray,
alignSelf: 'center',
justifyContent: 'center',
alignItems: 'center',
marginTop: h(10)
},
buttonText: {
color: colors.black,
fontWeight: 'bold'
},
settingsButton: {
position: 'absolute',
top: Platform.OS === 'ios' ? paddingTop : 0,
left: w(10),
borderRadius: w(30)
}
})
【问题讨论】:
-
第 191 行是哪一行?
-
-
这是第 191 行的完整部分 -
-
尝试把这部分的代码去掉,然后逐段添加
-
@JB_DELR 试过了,但没有成功
标签: javascript reactjs react-native