为什么 useState 在 React Native 中不起作用?

Why useState is not working in React Native?

我在 React Native Expo 中开发的应用程序中出现我无法理解的错误。错误如下;在 asyncstorage 中,我保留登录到应用程序的用户名。但是当我在页面加载时尝试设置它(useEffect)时,setLastUser 不起作用。当我在同一页面上尝试在键盘上执行 CTRL+S 时,我得到以下输出。

Prev CTRL+S

After CTRL+S

你能帮帮我吗?谢谢。

App.js代码

import { StatusBar } from 'expo-status-bar';
import React, { useState, useMemo } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import SignIn from './SignIn';
import SignUp from './SignUp';
import Conversation from './Conversation';
import Contacts from './Contacts';
import Settings from './Settings';
import Chats from './Chats';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import {Ionicons} from '@expo/vector-icons'
import { UserProvider } from './UserContext';
import { LogBox } from "react-native"


const Stack = createNativeStackNavigator();
const Tabs = createBottomTabNavigator();

const TabsNavigator = () => (
  <Tabs.Navigator screenOptions={({ route }) => ({
    tabBarIcon: ({ focused, color, size }) => {
      return <Ionicons name={route.name  === "Chats" ? "chatbubble-ellipses-outline" :  route.name === "Contacts" ? "people-outline" : "settings-outline"} color={color} size={size}  />
    }})}>
    <Tabs.Screen name="Chats" component={Chats} />
    <Tabs.Screen name="Contacts" component={Contacts} />
    <Tabs.Screen name="Settings" component={Settings} />
  </Tabs.Navigator>
);

export default function App() {
  LogBox.ignoreAllLogs(true);
  // const [lastUser, setLastUser] = useState('none');
  // const value = useMemo(
  //   () => ({ lastUser, setLastUser }), 
  //   [lastUser]
  // );
  return (
    <UserProvider>
    <NavigationContainer>
    <Stack.Navigator>
      <Stack.Screen options={{headerShown : false }} name="SignIn" component={SignIn} />
      <Stack.Screen
            name="SignUp"
            component={SignUp}
            options={{  headerTitle:'Login', headerBackVisible : true, headerBackTitleVisible :true}}
          /> 
       <Stack.Screen name="Home" component={TabsNavigator} options={{headerShown : false, headerBackTitleVisible : false}}/> 
       <Stack.Screen name="Contacts" component={Contacts} options={{  headerTitle:'ChatApp'}}/> 
       <Stack.Screen name="Conversation" component={Conversation} options={{  headerTitle:'ChatApp'}}/> 

    </Stack.Navigator>
  </NavigationContainer>
  </UserProvider>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

SignIn.js代码

import { useNavigation } from '@react-navigation/core'
import React, { useEffect, useState, createContext, useContext } from 'react'
import { KeyboardAvoidingView, StyleSheet, Text, TextInput, TouchableOpacity, View, Image } from 'react-native'
import { borderColor } from 'react-native/Libraries/Components/View/ReactNativeStyleAttributes'
import { auth, firebase } from './firebase'
import { userContext } from './UserContext'
import AsyncStorage from '@react-native-async-storage/async-storage';

const SignIn = () => {

    const [email, setEmail] = useState('')
    const [password, setPassword] = useState('')
    const navigation = useNavigation()
    const value = useContext(userContext);

    const handleLogin = async() => {
      await auth
        .signInWithEmailAndPassword(email, password)
        .then(userCredentials => {
          const user = userCredentials.user;
          console.log('Logged in with:', user.email);
          getUser(user.email);
          navigation.replace("Home");
        })
        .catch(error => alert(error.message))
    }

    const getUser = async (email2) => {
      await firebase.database().ref().child('users').orderByChild('email').equalTo(email2).once('value').then((data) => {
        data.forEach((node) => {
              storeUser(node.val().username); // one data
            }
        )
   }
   )
  }

   const storeUser = async(data) => {
     try{
       await AsyncStorage.setItem('sertacKul', data);
     }catch(err){
       console.log(err);
     }
   }

    return(
        <KeyboardAvoidingView
      style={styles.container}
      behavior="padding"
    >
      <View style={styles.inputContainer}>
        <Image style={styles.logo} source={require('./img/logo.png')}>
        </Image>
        <TextInput
          placeholder="Email"
          value={email}
          onChangeText={text => setEmail(text)}
          style={styles.input}
        />
        <TextInput
          placeholder="Password"
          value={password}
          onChangeText={text => setPassword(text)}
          style={styles.input}
          secureTextEntry
        />
      </View>
      <View style={styles.buttonContainer}>
        <TouchableOpacity
          onPress={handleLogin}
          style={styles.button}
        >
          <Text style={styles.buttonText}>Login</Text>
        </TouchableOpacity>
        <TouchableOpacity
          //onPress={handleSignUp}
          onPress={() => navigation.navigate('SignUp')}
          style={[styles.button, styles.buttonOutline]}
        >
          <Text style={styles.buttonOutlineText}>Register</Text>
        </TouchableOpacity>
        <TouchableOpacity
          //onPress={handleSignUp}
          onPress={() => value.setData('ebebbebebe')}
          style={[styles.button, styles.buttonOutline]}
        >
          <Text style={styles.buttonOutlineText}>{value.lastUser}</Text>
        </TouchableOpacity>
      </View>
    </KeyboardAvoidingView>
    )
}
export default SignIn;

const styles = StyleSheet.create({
    container: {
      flex: 1,
      justifyContent: 'center',
      alignItems: 'center',
      backgroundColor : 'white'
    },
    logo :{
      resizeMode :'contain',
      width: '100%',
      marginBottom : 40
    },
    inputContainer: {
      width: '80%'
    },
    input: {
      backgroundColor: '#eeeeee',
      paddingHorizontal: 15,
      paddingVertical: 10,
      borderRadius: 10,
      marginTop: 5,
    },
    buttonContainer: {
      width: '60%',
      justifyContent: 'center',
      alignItems: 'center',
      marginTop: 40,
    },
    button: {
      backgroundColor: '#06d6cc',
      width: '100%',
      padding: 15,
      borderRadius: 10,
      alignItems: 'center',
    },
    buttonOutline: {
      backgroundColor: 'white',
      marginTop: 5,
      borderColor: '#06d6cc',
      borderWidth: 2,
    },
    buttonText: {
      color: 'white',
      fontWeight: '700',
      fontSize: 16,
    },
    buttonOutlineText: {
      color: '#06d6cc',
      fontWeight: '700',
      fontSize: 16,
    },
  })

Contact.js代码

import React, { useState, useEffect, useContext } from "react";
import {
  StyleSheet,
  View,
  TextInput,Text
} from "react-native";
import { auth, firebase } from "./firebase";
import { List, Avatar, Divider, FAB } from "react-native-paper";
import uuid from "react-native-uuid";
import moment from "moment";
import { userContext } from "./UserContext";
import AsyncStorage from '@react-native-async-storage/async-storage';

const Contacts = () => {

  const [username, setUsername] = useState("");

  const value = useContext(userContext);
  const [contactList, setContactList] = useState([{}]);
  const [lastUser, setLastUser] = useState('');

  useEffect(() => {
    setContactList([])
    setLastUser(() => getUserName()) // ıs not work
    console.log('deneme',lastUser)
    getContacts();
  }, [])

  async function getUserName(){
    let user = await AsyncStorage.getItem('sertacKul');
    return user;
   }

  const addFriend = () => {
    console.log(value.lastUser)
    firebase
      .database()
      .ref("/users/")
      .once("value")
      .then((data) => {
        let id = uuid.v4();
        firebase
          .database()
          .ref("/friendrelations/" + id)
          .set({
            id: id,
            user1: username,
            user2: lastUser,
            relationtype: "normal",
            createdDate: moment().format("DD/MM/YYYY HH:mm:ss"),
          })
          .then(() => alert("Friend added."));
      });
  };

  const getContacts = async() => {await firebase.database().ref().child('friendrelations').orderByChild('user2').equalTo(() => getUserName())
  .once('value').then(data => {
    data.forEach((node) => { setContactList(lastContacts => [...lastContacts, node.val().user1])})
  })}

  return (
    <View>
      <TextInput
        placeholder="Yeni Arkadaş"
        value={username}
        style={styles.input}
        onChangeText={(text) => setUsername(text)}
      />
      <FAB
        onPress={() => addFriend()}
        icon="plus"
        style={{ position: "absolute", right: 16 }}
      />
     {/*
     
     BURASI BURASI BURASI BURASI BURASI BURASI BURASI BURASI BURASI BURASI 
     {contactList && contactList.map((item)=>{
         return(         <List.Item onPress={() => navigation.navigate('Conversation')} title={item}
         left={() => <Avatar.Image source={require('./img/profile1.png')} size={53}/>}
         />
        )
     })} */}
         <Divider inset/>
      

    </View>
  );
};
export default Contacts;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: "white",
  },
  logo: {
    resizeMode: "contain",
    width: "100%",
    marginBottom: 40,
  },
  inputContainer: {
    width: "80%",
  },
  input: {
    backgroundColor: "#eeeeee",
    paddingHorizontal: 15,
    paddingVertical: 10,
    borderRadius: 10,
    marginTop: 5,
  },
  buttonContainer: {
    width: "60%",
    justifyContent: "center",
    alignItems: "center",
    marginTop: 40,
  },
  button: {
    backgroundColor: "#06d6cc",
    width: "100%",
    padding: 15,
    borderRadius: 10,
    alignItems: "center",
  },
  buttonOutline: {
    backgroundColor: "white",
    marginTop: 5,
    borderColor: "#06d6cc",
    borderWidth: 2,
  },
  buttonText: {
    color: "white",
    fontWeight: "700",
    fontSize: 16,
  },
  buttonOutlineText: {
    color: "#06d6cc",
    fontWeight: "700",
    fontSize: 16,
  },
});

您必须等待 getUserName 函数的响应。一个不错的选择是将 useEffect 的内容放在异步函数中。例如:

useEffect(() => {
    setContactList([]);
    updateLastUserName();
    getContacts();
}, []);

useEffect(() => {
   // Need to wait the lastUser state change to can use it
   console.log(lastUser);
}, [lastUser]);

async function updateLastUserName(){
    const username = await getUserName();
    setLastUser(username);
}

async function getUserName(){
    const user = await AsyncStorage.getItem('sertacKul');
    return user;
}