Reputation: 603
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
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
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