Ошибка React Stack Navigator: «Нарушение инварианта, недопустимый тип элемента» - PullRequest
0 голосов
/ 04 марта 2020

Я пытаюсь научить себя React Native + Firebase. Я следовал учебнику, указанному в https://levelup.gitconnected.com/how-to-use-the-react-context-api-to-build-react-native-expo-and-firebase-apps-adda840e52b0. Пример из учебного пособия: когда пользователь вошел в систему, навигатор приложений переходит на домашнюю страницу, которая состоит только из кнопки регистрации.

Я хотел создать BottomTabNavigator, который также включает компонент «Настройки» и фиктивный экран. Экран-заглушка появляется и работает, но когда я нажимаю на вкладку «Настройки», я получаю следующее сообщение об ошибке:

«Uncaught Invariant Violation: недопустимый тип элемента: ожидается строка (для встроенных в компонентах) или класс / функцию (для составных компонентов), но получил: undefined. Вы, вероятно, забыли экспортировать свой компонент из файла, в котором он определен. "

Это был мой код:

index. js

const SwitchNavigator = createSwitchNavigator(
  {
    Initial: Initial,
    Auth: AuthNavigation,
    App: AppNavigation
  },
  {
    initialRouteName: 'Initial'
  }
)

const AppContainer = createAppContainer(SwitchNavigator)

export default AppContainer

AppNavigation. js

import { createStackNavigator } from 'react-navigation-stack'
import { createAppContainer, createSwitchNavigator } from 'react-navigation';
import { createBottomTabNavigator } from 'react-navigation-tabs';
import Home from '../screens/Home';
import DummyScreen2 from '../screens/DummyScreen2'
import SettingsHook from '../screens/SettingsHook'

const AppNavigation =  createAppContainer(
  createBottomTabNavigator({
    Home: {
      screen: Home,
      navigationOptions: {
        tabBarLabel: 'Home',
      },
    },
    SettingsHook: {
      screen: SettingsHook,
      navigationOptions: {
        tabBarLabel: 'SettingsHook',
      },
    },
    DummyScreen2: {
      screen: DummyScreen2,
      navigationOptions: {
        tabBarLabel: 'DummyScreen2',
      },
    },
  })
);

AuthNavigation. js

const AuthNavigation = createStackNavigator(
  {
    Login: { screen: Login },
    Signup: { screen: Signup },
    ForgotPassword: { screen: ForgotPassword },
  },
  {
    initialRouteName: 'Login',
    headerMode: 'none'
  }
)

export default AuthNavigation

Настройки крючка. js

   const SettingsHook = () => {
    const [modalVisible, setmodalVisible] = useState(false)
    const [budget, setBudget] = useState(850)
    const [monthly, setMonthly] = useState(1700)
    const [notifications, setNotifications] = useState(true)
    const [newsletter, setNewsletter] = useState(false)
    const [editing, setEditing] = useState(null)
    const [profile, setProfile] = useState({})
    const [firstName, setFirstName] = useState('')
    const [lastName, setLastName] = useState('')
    const [email, setEmail] = useState('')
    const [cardNumber, setCardNumber] = useState(0)
    const [last3Digits, setLast3Digits] = useState(0)


    useEffect(()=>{
        setProfile(profile)
    })

    const toggleEdit = (name) => {
        // const { editing } = this.state;
        // this.setState({ editing: !editing ? name : null });
        setEditing(!editing ? name : null )
    }


    const renderEdit =(name) => {
        // const { profile, editing } = this.state;

        if (editing === name) {
            return (
                <TextInput
                    defaultValue={profile[name]}
                    onChangeText={text => handleEdit([name], text)}
                />
            )
        }
        return <Text bold>{profile[name]}</Text>
    }

    const handleEdit = (name, text) => {
        profile[name] = text;

        // this.setState({ profile });
        setProfile(profile)
    }

    const setModalVisible = (visible) => {
        // this.setState({ modalVisible: visible });
        setmodalVisible(visible)
    }

    const handleSubmit=()=> {
        // do the things
        Alert.alert('Updated payment method successfully!')

        // this.setState({ modalVisible: false })
        setmodalVisible(false)
    }


    const addPaymentInfo= () => {
        return (
            <Modal animationType="slide" visible={modalVisible} onRequestClose={() => setmodalVisible(false)}>
                <Text> Payment Information </Text>
                <View>
                    <TextInput
                        placeholder="First Name"    
                        onChangeText={text => setFirstName(text)}
                    />
                    <TextInput
                        placeholder="Last Name"
                        // onChangeText={text => this.setState({lastName: text })}
                        onChangeText={text => setLastName(text)}
                    />

                    <TextInput
                        placeholder="Email"
                        keyboardType='email-address'
                        onChangeText={text => setEmail(text)}
                    />
                    <TextInput
                        secureTextEntry={true}
                        keyboardType='number-pad'
                        placeholder="Credit Card Number"
                        onChangeText={text => setCardNumber(text)}
                    />
                    <TextInput
                        secureTextEntry={true}
                        keyboardType='numeric'
                        placeholder="Last 3 digits:"
                        onChangeText={text => setLast3Digits(text)}
                    />

                </View>
                {/* <Button gradient onPress={() => setmodalVisible(false)}> */}
                <Button gradient onPress={handleSubmit}>
                    <Text center white>Submit</Text>
                </Button>
            </Modal>
        )
    }



        // const { profile, editing } = this.props;
        return (
            <Block>
                <Block flex={false} row center space="between" style={styles.header}>
                    <Text h1 bold>Settings Hook</Text>
                    <Button>
                        <Image source={profile.avatar} style={styles.avatar} />
                    </Button>
                </Block>
                <ScrollView showsVerticalScrollIndicator={false}>

                <Block style={styles.inputs}>
                        <Block row space="between" margin={[10, 0]} style={styles.inputRow}>
                            <Block>
                                <Text gray2 style={{ marginBottom: 10 }}>Username</Text>
                                {renderEdit('username')}
                            </Block>
                            <Text medium secondary onPress={() => toggleEdit('username')}>
                                {editing === 'username' ? 'Save' : 'Edit'}
                            </Text>
                        </Block>
                        <Block row space="between" margin={[10, 0]} style={styles.inputRow}>
                            <Block>
                                <Text gray2 style={{ marginBottom: 10 }}>Location</Text>
                                {renderEdit('location')}
                            </Block>
                            <Text medium secondary onPress={() => toggleEdit('location')}>
                                {editing === 'location' ? 'Save' : 'Edit'}
                            </Text>
                        </Block>
                        <Block row space="between" margin={[10, 0]} style={styles.inputRow}>
                            <Block>
                                <Text gray2 style={{ marginBottom: 10 }}>E-mail</Text>
                                <Text bold>{profile.email}</Text>
                            </Block>
                        </Block>
                    </Block>

                    <Button onPress={() => setmodalVisible(true)}>
                        <Text center caption gray>Update Payment Information</Text>
                    </Button>
                    {addPaymentInfo()}


                    <Divider margin={[theme.sizes.base, theme.sizes.base * 2]} />

                    <Block style={styles.sliders}>
                        <Block>
                            <Text gray2>Budget</Text>
                            <Slider
                                minimumValue={0}
                                maximumValue={1000}
                                style={{ height: 19 }}
                                thumbStyle={styles.thumb}
                                trackStyle={{ height: 6, borderRadius: 6 }}
                                minimumTrackTintColor={theme.colors.secondary}
                                maximumTrackTintColor="rgba(157, 163, 180, 0.10)"
                                value={budget}
                                onValueChange={value => setBudget(value)}
                            />
                            <Text caption gray2 right>$1,000</Text>
                        </Block>

                    </Block>
                    <Divider />

                    <Block style={styles.toggles}>
                        <Block row center space="between">
                            <Text gray2>Notifications</Text>
                            <Switch
                                value={notifications}
                                onValueChange={value => setNotifications(value)}
                            />
                        </Block>
                        <Block row center space="between">
                            <Text gray2>Newsletter</Text>
                            <Switch
                                value={newsletter}
                                onValueChange={value => setNewsletter(value)}
                            />
                        </Block>
                    </Block>
                </ScrollView>
            </Block>
        );
}

SettingsHook.defaultProps = {
    profile: mocks.profile,
}
export default SettingsHook

DummyScreen2. js

export default class DummyScreen2 extends Component {  
  render() {
    return (
      <View style={styles.container}>
        <Block>
        <Text>Dummy Screen 2</Text>
        </Block>
        <Button
          title='Signout'
          // onPress={this.handleSignout}
          titleStyle={{
            color: '#F57C00'
          }}
          type='clear'
        />

      </View >
    )
  }
}
...