【问题标题】:Warning: Functions are not valid as a React child While Upgrading to 63.2警告:升级到 63.2 时,函数作为 React 子级无效
【发布时间】: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


【解决方案1】:

原来问题出在包键盘感知滚动视图上。需要将软件包更新到最新版本。

【讨论】:

    【解决方案2】:

    您是否尝试过扁平化样式?喜欢:
    contentContainerStyle={Stylesheet.flatten([ styles.container, { backgroundColor: isDayTime ? colors.white : colors.black }])}
    你可以找到文档here

    【讨论】:

      猜你喜欢
      • 2018-12-15
      • 2018-11-05
      • 2019-06-16
      • 2020-03-09
      • 1970-01-01
      • 1970-01-01
      • 2018-10-16
      • 2020-11-18
      • 1970-01-01
      相关资源
      最近更新 更多