【问题标题】:React Native: useState setter doesn't rerenderReact Native:useState setter 不会重新渲染
【发布时间】:2020-09-27 19:40:14
【问题描述】:

我是 react 和 javascript 的新手。我试图在登录用户时显示 ActivityIndi​​cator,但是 setIsLoading 方法实际上并没有改变状态并调用重新渲染。 handleLogin 方法在单击按钮时被调用,当我单击按钮时,useEffect 不会打印到控制台,这意味着它没有被调用。此外,console.log(isLoading) 仍将值显示为 false,它被初始化为。奇怪的是,当我注释掉整个 firebase 部分时,我能够让它工作,我想知道是否有人可以帮助我理解为什么会这样?谢谢。

import React, { useState, useEffect } from 'react'
import firebase from '../firebase'
import { ActivityIndicator, StyleSheet, Text, TextInput, View, Button} from 'react-native'
export default function LoginScreen({navigation}) {
    const [email, setEmail] = useState('')
    const [password, setPassword] = useState('')
    const [errorMessage, setErrorMessage] = useState(null)
    const [isLoading, setIsLoading] = useState(false)
    const [showLoader, setShowLoader] = useState(false)

    useEffect(() => {
        setShowLoader(isLoading)
        console.log('useEffect')
    },[isLoading])

    const handleLogin = () => { 
        setIsLoading(true)
        console.log(isLoading)

        firebase.auth().signInWithEmailAndPassword(email, password)
        .then(() => { navigation.navigate('Home')})
        .then(setIsLoading(false))
        .catch((error) => {setErrorMessage(error.message)})

        console.log('handleLogin')
    }
    return (
      <View style={styles.container}>
        <Text>Login</Text>
        {errorMessage &&
          <Text style={{ color: 'red' }}>
            {errorMessage}
          </Text>}
        <TextInput
          style={styles.textInput}
          autoCapitalize="none"
          placeholder="Email"
          onChangeText={email => setEmail(email)}
          value={email}
        />
        <TextInput
          secureTextEntry
          style={styles.textInput}
          autoCapitalize="none"
          placeholder="Password"
          onChangeText={password => setPassword(password)}
          value={password}
        />
        <Button title="Login" onPress={handleLogin} />
        <Button
          title="Don't have an account? Sign Up"
          onPress={() => navigation.navigate('SignUp')}
        />
        {
            showLoader && <ActivityIndicator/>
        }   
      </View>
    )
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  textInput: {
    height: 40,
    width: '90%',
    borderColor: 'gray',
    borderWidth: 1,
    marginTop: 8
  }
})

编辑:谢谢,我发现直到方法 handleLogin 完成后才调用 useEffect,所以 isLoading 设置为 true,但在登录过程后再次设置为 false,所以到时候使用 useEffect被调用,它看到 isLoading 状态没有改变,所以 useEffect 没有被调用。如果有人对如何绕过这个流程有任何想法(所以在登录过程之前调用 useEffect 或其他东西),我将不胜感激。谢谢!

【问题讨论】:

  • 你能添加你的组件的整个代码吗?
  • 您正在设置 setIsLoading(true) 并且您在下一行阅读它,但实际上值将在重新渲染时启动..您确定在按钮单击时调用 handleLogin 吗?

标签: javascript react-native


【解决方案1】:

在执行 setIsLoading 之前,您似乎已经离开了屏幕,虽然我不知道如果没有其余代码,这是否会成为问题。

console.log(isLoading) 为 false,因为 useState 是异步的,setIsLoading 是到达下一行代码时尚未解决的承诺。

这行代码isLoading? setShowLoader(true) : setShowLoader(false) 会比setShowLoader(isLoading) 更简洁

【讨论】:

  • 根据我的测试:我正在考虑这一点,所以我在 useEffect() 中添加了控制台日志,并且故意没有输入登录凭据,这样我就不会离开。因此,当按下按钮时,我认为最终会调用 useEffect() ,但它从未在控制台中打印。也感谢干净的代码建议!永远感激这一点。
猜你喜欢
  • 2016-05-09
  • 2021-01-13
  • 1970-01-01
  • 2023-03-13
  • 2020-07-06
  • 1970-01-01
  • 2023-03-28
  • 2017-01-21
  • 2021-06-13
相关资源
最近更新 更多