erv
erv

Reputation: 603

App function returning nothing from asynchronous operation in React Native

I'm totally new to React Native, and this is the first code I've written. I'm unsure how to return my jsx from my App() enclosing function when it has an asynchronous operation within it. I suspect this is a really basic error, so hopefully my code will show the problem clearly:

import React from 'react';
import { Text, View, TextInput, Button, Alert } from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';

//check if logged in, if not show login screen
export default function App() {
    AsyncStorage.getItem("user")
    .then((user) => {
        if(user) {
            //user validated
            return (
                <View>
                    <Text>Logged In!</Text>
                </View>
            );
    
        } else {
            //user not logged in, therefore show login screen
            return (
                <View>
                    <Text>Enter Your Username</Text>
                    <TextInput 
                        maxLength={16} 
                    />
                    <Button 
                        title="Login"
                    />
                </View>
            );
        }
    });
}

The outer App() function is obviously not returning anything, but I'm unsure of how to make it wait and return the jsx from the inner asynchronous function.

What I've tried: I initially used async/await on the outer function and AsyncStorage.getItem(...), but that returned the following error: Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.

Next I tried a different approach after reading an answer to a similar question here at SO:

export default function App() {
    return (
        <View>
            <Login />
        </View>
    );

    async function Login() {
        const user = await AsyncStorage.getItem("user");

        if(user) {
            return (
                <Text>Logged In!</Text>
            );
        } else {
            return (
                <Text>Enter Your Username</Text>
            );
        }
    }
}

But am getting the same error as above when I used async/await.

I'm a rank newbie to React Native, so please hit me with the "for dummies" explanation.

Upvotes: 0

Views: 1235

Answers (2)

Emik lad
Emik lad

Reputation: 23

I prefer class components and as such, I'd do this: export default class App extends Component {

constructor(props) {
    super(props)

    this.state = {
        user: null //intialize a user state with null
    }
}

componentDidMount = () => {
    const user = await AsyncStorage.getItem("user");//get the user on component mount and set state to user
    this.setState({ user }) // this.setState({ user: user }) does same
}

render() {
    const { user } = this.state; //destructure state here
    return (
        <>
            <View>
                <Login />
            </View>

            {
                user ? //if user show logged in else show enter username
                    <Text>Logged In!</Text> :
                    <Text>Enter Your Username</Text>
            }
        </>
    )
}

}

Upvotes: 0

Ramesh Reddy
Ramesh Reddy

Reputation: 10662

As I said in the comments since your JSX is wrapped in a promise(because async functions always return a promise), React says Objects are not valid as a React child.

You can use useState and useEffect hooks to maintain the user state and to get the user. For example:

function Login() {
    const [user, setUser] = useState();
    useEffect(() => {
        if(!user) {
            AsyncStorage.getItem('user')
                .then(user => setUser(user));
                // .catch()
        }
    }, [user, setUser]) // also add any other required dependencies

    if(user) {
        return (
            <Text>Logged In!</Text>
        );
    } else {
        return (
            <Text>Enter Your Username</Text>
        );
    }
}

Upvotes: 2

Related Questions