Home > Enterprise >  Invariant Violation: Cannot specify both value and children
Invariant Violation: Cannot specify both value and children

Time:08-13

I'm new to react native and I have no idea how to solve this.

This is my Login.js

import React from 'react';
import { View, StyleSheet, StatusBar } from 'react-native';
import { Headline, Paragraph, TextInput, Button, Snackbar, Portal } from 'react-native-paper';
import UserModel from '../../app/models/UserModel';
import { ScrollView } from 'react-native-gesture-handler';

const Login = props => {
    const [identifier, setIdentifier] = React.useState('');
    const [password, setPassword] = React.useState('');
    const [visible, setVisible] = React.useState(false);
    const [loading, setLoading] = React.useState(false);
    const [error, setError] = React.useState(false);

    const validateInput = () => {
        let errors = false;
    
        if (!identifier || identifier.length === 0) {
            errors = true;
        }
    
        if (!password || password.length === 0) {
            errors = true;
        }
    
        return !errors;
    };

    const authenticateUser = async () => {
        if (validateInput()) {
            setLoading(true);
            const user = new UserModel(identifier, password);
        
            try {
                await user.login();
            } catch (err) {
                setError(err.message);
                setVisible(true);
                setLoading(false);
            }
        } else {
            setError('Please fill out all *required fields');
            setVisible(true);
            setLoading(false);
        }
    };

    return (
        <Portal.Host>
            <View style={styles.base}>
                <>
                    <StatusBar backgroundColor="#ffffff" barStyle="dark-content" />
                </>

                <View style={styles.header}>
                    <Headline style={styles.appTitle}>To-do list App</Headline>
                    <Paragraph style={styles.appDesc}>
                        Authenticate with Strapi to access the TodoApp.
                    </Paragraph>
                </View>

                <View style={styles.divider} />
                <TextInput
                    onChangeText={text => setIdentifier(text)}
                    label="*Username or email"
                    placeholder="*Username or email">
                    {identifier}
                </TextInput>

                <View style={styles.divider} />
                <TextInput
                    onChangeText={text => setPassword(text)}
                    label="*Password"
                    placeholder="*Password"
                    secureTextEntry>
                    {password}
                </TextInput>



                <View style={styles.divider} />
                <Button
                    loading={loading}
                    disabled={loading}
                    style={styles.btn}
                    onPress={() => authenticateUser()}
                    mode="contained">
                    Login
                </Button>
                <View style={styles.divider} />
                <View style={styles.divider} />


                <>
                    {/**
            * We use a portal component to render
            * the snackbar on top of everything else
            * */}
                    <Portal>
                        <Snackbar visible={visible} onDismiss={() => setVisible(false)}>
                            {error}
                        </Snackbar>
                    </Portal>
                </>
            </View>
        </Portal.Host>
    );
};

const styles = StyleSheet.create({
    base: {
        flex: 1,
        paddingLeft: 16,
        paddingRight: 16,
        alignContent: 'center',
        justifyContent: 'center',
        backgroundColor: '#dedede'
    },
    divider: {
        height: 16,
    },
    headline: {
        fontSize: 30,
    },
    appDesc: {
        textAlign: 'center',
    },
    header: {
        padding: 32,
    },
    appTitle: {
        textAlign: 'center',
        fontSize: 35,
        lineHeight: 35,
        fontWeight: '700',
    },
    btn: {
        height: 50,
        paddingTop: 6,
    },
});

export default Login;

For extra context, I am trying to create a basic react-native expo app with strapi as the backend. The error comes up when I try to type in the "username or email" bar. I don't know how necessary this is but the entire error is:

Invariant Violation: Cannot specify both value and children.

This error is located at:
    in NavigationContainer (created by Authentication)
    in Authentication (created by App)
    in ThemeProvider (created by Provider)
    in RCTView (created by View)
    in View (created by Portal.Host)
    in Portal.Host (created by Provider)
    in Provider (created by App)
    in PersistGate (created by App)
    in Provider (created by App)
    in App (created by ExpoRoot)
    in ExpoRoot
    in RCTView (created by View)
    in View (created by AppContainer)
    in RCTView (created by View)
    in View (created by AppContainer)
    in AppContainer
    in main(RootComponent)
at node_modules\expo\build\environment\react-native-logs.fx.js:27:4 in error
at node_modules\react-native\Libraries\Core\ExceptionsManager.js:95:4 in reportException
at node_modules\react-native\Libraries\Core\ExceptionsManager.js:141:19 in handleException
at node_modules\react-native\Libraries\Core\setUpErrorHandling.js:24:6 in handleError
at node_modules\expo-error-recovery\build\ErrorRecovery.fx.js:12:21 in ErrorUtils.setGlobalHandler$argument_0
at node_modules\@babel\runtime\helpers\regeneratorRuntime.js:86:13 in tryCatch
at node_modules\@babel\runtime\helpers\regeneratorRuntime.js:66:31 in <anonymous>
at node_modules\@babel\runtime\helpers\regeneratorRuntime.js:86:13 in tryCatch
at node_modules\@babel\runtime\helpers\regeneratorRuntime.js:124:27 in invoke
at node_modules\@babel\runtime\helpers\regeneratorRuntime.js:130:16 in PromiseImpl.resolve.then$argument_0
at node_modules\promise\setimmediate\core.js:37:13 in tryCallOne
at node_modules\promise\setimmediate\core.js:123:24 in setImmediate$argument_0
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:248:12 in _allocateCallback$argument_0
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:112:14 in _callTimer
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:162:14 in _callReactNativeMicrotasksPass
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:413:41 in callReactNativeMicrotasks 
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:391:6 in __callReactNativeMicrotasks
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:133:6 in __guard$argument_0   
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:368:10 in __guard
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:132:4 in flushedQueue

CodePudding user response:

The problem is in your TextInput components. You're giving the TextInputs "children", which is what React calls it when you nest a component inside another. You're doing:

  <TextInput ...>
    {identifier}
  </TextInput>

However, the value of TextInputs is not meant to be specified this way. You should pass the identifier into the value prop of the TextInput.

  <TextInput
    value={identifier}
    ...
  />

You're not explicity passing the value prop in your code example, but I think that passing the placeholder or label props is setting the value under the hood.

Check the React Native TextInput docs for examples of how these are typically used.

  • Related