reactjs - 更新 useState 和 AsyncStorage 并根据给定结果重新渲染屏幕

标签 reactjs react-native asyncstorage

我是 React Native 的新手,我目前正在尝试从网站获取凭证数据并将其保存到设备内存中。但是我遇到了一些关于它的问题!

我的流程:

  1. 当应用启动时,应用将检查 asyncStorage 是否有凭据。

  2. 如果是这样,我们直接进入应用程序。否则我们进入 RootStackScreen(又名登录屏幕)***(问题 #1)

  3. (LOGIN) 用户将在文本输入中输入他/她的登录信息,该文本输入将保存在 useState 中。

  4. 使用函数“loginHandle”,使用来自 useState 的信息调用提取请求,我们使用返回的数据设置凭证。**(问题 #2)

  5. 应用程序应重新呈现并看到有凭证并加载到主屏幕中。 ***(问题 #3)

但是,我遇到了 2 个问题。

  1. *** 即使当我在 return(...) 中检查 appLoad.credentials 时 asyncStorage 确实包含凭据,它也会返回 null。但是,它在我的 useEffect() 中返回了正确的值。我想通过使用 useEffect() 我在屏幕渲染之前的 ComponentsDidMount 期间调用函数。那么 appLoad.credentials 不应该包含一个字符串吗?

  2. 在我的 console.log(credential) 上总是落后一步。 IE。我按一次登录按钮。控制台日志将返回 null。但是,我认为由于 console.log() 在 fetch 命令之后,因此应该在 console.log 调用之前设置凭据!

  3. 如何让应用程序重新呈现。我在网上看到有关强制重新渲染的内容,但我听说这很糟糕!

App.js


import AsyncStorage from '@react-native-community/async-storage';
...

export default function App() {

  const STORAGE_KEY = '@deviceCredentials';
  const [data, setData] = useState('');

  const appLoad = {
    isLoading: true,
    credentials: null
  };


  //Runs during ComponentsDidMount
  useEffect(() => {
    setTimeout(async () => {

      //In 1000ms try to get credentials
      try {
        appLoad.credentials = await AsyncStorage.getItem(STORAGE_KEY);
        console.log(appLoad.credentials);
      } catch (e) {
        console.log(e);
      }
    }, 1000);
  }, []);


  //Render
  return (
 
      <NavigationContainer>
        {/* If credentials is not null then we can go straight into Main screen, 
            otherwise we go to Login Screen */}
        {appLoad.credentials !== null ? (
          <Drawer.Navigator drawerContent={props => <DrawerContent {...props} />}>
            <Drawer.Screen name="MusteringDrawer" component={MainTabScreen} />
          </Drawer.Navigator>
        )
          :
          <RootStackScreen />
        }
      </NavigationContainer>

  );
};

登录.js

...
...
const [data, setData] = useState({
                               username: '',
                               password: '',
                               ...
})
const [credential, setCredential] = useState({ data: null });

const STORAGE_KEY = '@deviceCredentials';

...
...
//Handles user data
const handleValidUser = (val) => {
            setData({
                ...data,
                username: val,
            });
}


const loginHandle = () => {
        fetch(url + data.password + data.username)
            .then(x => x.text())
            .then(y => {
                setCredential({ data: y });
            });
            console.log(credential);
            AsyncStorage.setItem(STORAGE_KEY, credential);
    }



return( 
     <Text>Username</Text>
     <TextInput
        placeholder="Your Username"
        onChangeText={(val) => handleValidUser(val)}
        onEndEditing={(e) => handleValidUser(e.nativeEvent.text)}
      />
     <Text>Password</Text>
     <TextInput
         placeholder="Your Password"
         onChangeText={(val) => handlePasswordChange(val)}
      />


      <View style={styles.button}>
            <TouchableOpacity  onPress={() => { loginHandle(); }}>
                   <Text>Sign In</Text>
            </TouchableOpacity>
      </View>

最佳答案

您是否意识到:

const appLoad = {
    isLoading: true,
    credentials: null
};

每次渲染都重新定义了吗?更重要的是,如果在 effect hook 中设置了值,react 无法知道它已更改,因此不会重新渲染。如果它确实重新渲染(出于某些完全不同的原因,这不会重新渲染)...好吧,新变量 :D。

您想要的是在所有渲染中记住这样的数据。您肯定知道,您可以通过使用 useState Hook 来执行此操作。

免责声明:阅读我在代码中添加的注释非常重要,它们对于此代码的工作/成为“最佳实践”至关重要。此代码也未经过测试,但您应该能够使用您的一些优秀开发技能使其正常工作:)

export default function App() {
    // Remove this, seems to be a leftover from testing 
    // const [data, setData] = useState('');
    
    const [isLoading, setIsLoading] = useState(true);
    const [credentials, setCredentials] = useState(null);

    // Check for credentials in the first render
    useEffect(() => {
        // 1. I'm not sure why you add a delay, It will probably only make your app appear sluggish
        // 2. Use effect callbacks should not be made async, see this post 
        // https://stackoverflow.com/questions/53332321/react-hook-warnings-for-async-function-in-useeffect-useeffect-function-must-ret
        async function fetchCredentials() {
            setCredentials(await AsyncStorage.getItem(STORAGE_KEY));
            setIsLoading(false); 
        }

        fetchCredentials();
    }, []);

    // Whatever your render code may be
    return null;
}

很可能是我没有解决你的问题(我可能没有理解你,而且大多数时候我一般都有点傻)。在这种情况下,请不要犹豫,通过评论回复我。

干杯,快乐编码!

关于reactjs - 更新 useState 和 AsyncStorage 并根据给定结果重新渲染屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63042232/

相关文章:

reactjs - 无法在 React 中编辑 Material UI 文本字段

javascript - 带有键但没有值的 react.js setState 调用?

android - 图像无法在 Android 7.0 (API 24) 上呈现

android - 如何修复 "SDK location not found..."?

react-native iOS 模拟器网络连接

javascript - React-native:在从存储中获取数据之前渲染 View

javascript - Auth0 忽略范围选项

javascript - 使用 react 钩子(Hook)设置值的问题

react-native - AsyncStorage 未解析或拒绝

javascript - react native 异步存储不保存并且没有错误