【问题标题】:React-Native component updates when I save changes, and not upon starting. [Firebase, useEffect]React-Native 组件在我保存更改时更新,而不是在启动时更新。 [Firebase,使用效果]
【发布时间】:2021-03-02 09:18:05
【问题描述】:

我还是一个新手程序员,所以希望我的代码是可以理解的。

我有一个 Firestore 数据库,访问存储的数据没有问题,问题在于 React 组件或 Expo。

这个问题出现在我的软件的各个部分,我只包括一个(如果你们帮我解决它,我想我可以解决其他的)

这是我的身份验证流程:

LoginForm.js(使用电子邮件创建用户并通过 Firebase)-> AddExtraInfo(保存一些配置文件数据)-> ProfileInfoWorker(保存一些额外数据)-> 帐户(如果用户已登录,则转到 UserGuest,否则转到 UserLogged) -> UserLogged(获取信息)-> InfoUser(显示信息的组件)

  //  UserLogged.js
  export default function UserLogged(props) {
  const [userInfo, setUserInfo] = useState(null);
  const [perfilData, setPerfilData] = useState("");

  firebase.auth().onAuthStateChanged((user) => {
    setUserInfo(user);
  });

  useEffect(() => {
    if (userInfo) {
      setLoading(true);
      let ref = db.collection("perfil-final");
      let query = ref
        .where("userId", "==", firebase.auth().currentUser.uid)
        .get()
        .then((snapshot) => {
          if (snapshot.empty) {
            console.log("No matching documents.");
            return;
          }
          snapshot.forEach((doc) => {
            setPerfilData(doc.data());
          });
          setLoading(false);
        })
        .catch((err) => {
          console.log("Error getting documents", err);
        });
    }
  }, []); 
   return (
    <View style={styles.viewUserInfo}>
      {userInfo && (
        <InfoUser
          userInfo={userInfo}
          perfilData={perfilData}
        />
      )}
    </View>

我在这里打印信息

//InfoUser.js
export default function InfoUser(props) {
  const {
    userInfo: { uid, displayName, email },
    perfilData,
  }
   return (
    <View>
      <View>
        <Text>
          {displayName ? displayName : "Anonymous"}
        </Text>
        <Text>{email ? email : "Anonymous"}</Text>
      </View>

    </View>
  );
}

问题是,当我进入 UserLogged 屏幕时,它会加载“匿名”,但如果我在代码编辑器上按 CTRL + S 并获得刷新警报,我会得到正确的数据。怎么了? 我假设我的代码一开始是空的,所以它没有显示数据,但是当它改变时,为什么它不更新?

提前致谢,干杯!

编辑:

// RegisterForm.js
export default function RegisterForm(props) {
  const [formData, setFormData] = useState(defaultFormValue());

  const onChange = (e, type) => {
    setFormData({ ...formData, [type]: e.nativeEvent.text });
    const [loading, setLoading] = useState(false);
    const navigation = useNavigation();
    //.. here I validate empty fields and then..
    setLoading(true);
    firebase
      .auth()
      .createUserWithEmailAndPassword(formData.email, formData.password)
      .then(() => {
        setLoading(false);
        navigation.navigate("extrainfo");
      })
      .catch(() => {
        setLoading(false);
        console.log("Email already on use");
      });
  };
  return (
    <View style={styles.formContainer}>
      <Input
        placeholder="Email"
        containerStyle={styles.inputForm}
        onChange={(e) => onChange(e, "email")}
      />
      <Input
        placeholder="Password"
        containerStyle={styles.inputForm}
        onChange={(e) => onChange(e, "password")}
        password={true}
        secureTextEntry={showPassword ? false : true}
      />
      <Input
        placeholder="Repeat Password"
        containerStyle={styles.inputForm}
        onChange={(e) => onChange(e, "repeatPassword")}
        password={true}
        secureTextEntry={showRepeatPassword ? false : true}
      />
      <Button
        title="Join"
        containerStyle={styles.btnRegisterForm}
        buttonStyle={styles.btnRegister}
        onPress={onSubmit}
      />
      <Loading isVisible={loading} text="Making account..." />
    </View>
  );
}
function defaultFormValue() {
  return {
    email: "",
    password: "",
    repeatPassword: "",
  };
}

在这里,当用户按下帐户选项卡时,我会重定向,如果用户已登录,则转到 UserLogged,如果未登录,则转到 UserLogged 屏幕。

//Account.js
export default function Account() {
  const [login, setLogin] = useState(null);
  firebase.auth().onAuthStateChanged((user) => {
    !user ? setLogin(false) : setLogin(true);
  });

  if (login === null) return <Loading isVisible={true} text="Cargando..." />;

  return login ? <UserLogged /> : <UserGuest />;
}

这里我使用 React Navigation,尝试首先获取 userType,以便在用户是工作人员时显示一些选项卡,如果用户是客户端则显示其他选项卡。

//Navigation.js
export default function Navigation(props) {
  const [userType, setUserType] = useState("");
  const [userInfo, setUserInfo] = useState("")
  const [nombreRuta, setNombreRuta] = useState("Solicitudes");
  const [login, setLogin] = useState(null);

  firebase.auth().onAuthStateChanged((user) => {
    !user ? setLogin(false) : setLogin(true);
    if (!user) {
    userType("");
    }else{
    setUserInfo(user);
    }
  });

  useEffect(() => {
    let isSubscribed = true;
    if (login) {
      let perfilRef = db.collection("perfiles");
      perfilRef
        .where("userId", "==", firebase.auth().currentUser.uid)
        .get()
        .then((snapshot) => {
          if (snapshot.empty) {
            console.log("No matching documents.");
            return;
          }
          snapshot.forEach((doc) => {
            if (isSubscribed) {
              setTipoUsuario(doc.data().userType);
            }
          });
        })
        .catch((err) => {
          console.log("Error getting documents", err);
        });
    }
    return () => (isSubscribed = false);
  }, [userInfo]); //Tried with: login and userType

  return (
    <NavigationContainer>
      <Tab.Navigator
        initialRouteName="requests"
        tabBarOptions={{
          inactiveTintColor: "#646464",
          activeTintColor: "#F7931C",
        }}
        screenOptions={({ route }) => ({ 
          tabBarIcon: ({ color }) => screenOptions(route, color),
        })}
      >
        {userType == "worker" && (
          <Tab.Screen
            name="solicitudesworker"
            component={RequestsWorkerStack}
            options={{ title: "Requests" }}
          ></Tab.Screen>
        )}
        {userType == "client" && (
          <Tab.Screen
            name="restaurants"
            component={RequestsStack}
            options={{ title: "Requests" }}
          ></Tab.Screen>
        )}

        <Tab.Screen
          name="topworkers"
          component={topworkers}
          options={{ title: "Top Workers" }}
        ></Tab.Screen>
        <Tab.Screen
          name="search"
          component={SearchStack}
          options={{ title: "Search" }}
        ></Tab.Screen>

        <Tab.Screen
          name="account"
          component={AccountStack}
          options={{ title: "Account" }}
        ></Tab.Screen>
      </Tab.Navigator>
    </NavigationContainer>
  );
}


【问题讨论】:

    标签: javascript firebase react-native google-cloud-firestore react-hooks


    【解决方案1】:

    发生的事情是你的 useEffect 在组件的挂载上被调用,然后再也没有被调用。

    这是因为使用没有依赖数组的 useEffect 只会调用一次函数。它在 userInfo 状态有机会更新之前被调用,因此它的所有方式都为空。 (当您热重载时,它会强制调用 useEffect。这在生产中不会发生)。

    您需要将 userInfo 传递到 useEffect 的依赖数组中。这样当 userInfo 状态更新时,会再次调用 useEffect。

    useEffect(() => {
    if (userInfo) {
      setLoading(true);
      let ref = db.collection("perfil-final");
      let query = ref
        .where("userId", "==", firebase.auth().currentUser.uid)
        .get()
        .then((snapshot) => {
          if (snapshot.empty) {
            console.log("No matching documents.");
            return;
          }
          snapshot.forEach((doc) => {
            setPerfilData(doc.data());
          });
          setLoading(false);
        })
        .catch((err) => {
          console.log("Error getting documents", err);
        });
    }
    }, [userInfo]);
    

    让我知道这对你有什么好处。

    【讨论】:

    • 还是一样,只是在我热重载时加载信息。此外,这仅在我创建新用户时发生,并且我被重定向到 UserLogged 屏幕,当我注销然后登录时,数据加载正常。
    • 请您使用 LoginForm.js 和您认为与此流程相关的任何其他代码更新您的答案,因为听起来有些状态没有在某处更新
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    • 2020-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多