【问题标题】:Hot to pass state from main App.js to screen components using react navigation in react native使用 React Native 中的 React Navigation 将状态从主 App.js 传递到屏幕组件
【发布时间】:2020-11-25 17:08:33
【问题描述】:

我正在用 react native 制作一个小应用程序,它是一个基本的登录工作流程,它使用几个屏幕(登录和主页),根据用户状态显示;在 App.js 中,我有一堆状态用于启用/禁用视图、按钮、显示用户名等。 我在外部组件中有登录屏幕和主屏幕。我想知道(除了使用上下文之外)是否有办法让这些状态(和功能)可用于子屏幕

这是我的代码的一部分:

App.js

export default function App() {
  const [isLoading, setIsLoading] = useState(true);
  const [isLogged, setIsLogged] = useState(false);
  const [userToken, setUserToken] = useState(null);
  const [userProfile, setUserProfile] = useState(null);
  const [email, setEmail] = useState(null);
  const [password, setPassword] = useState(null);
  const [loggingIn, setloggingIn] = useState(false);
  const [error, setError] = useState(null);

  const AppStack = createStackNavigator();

  useEffect(() => {
    AsyncStorage.getItem('userProfile').then((value) => {
      if (value) {
        console.log(JSON.parse(value)),
          setUserProfile(JSON.parse(value)),
          setIsLoading(false),
          setIsLogged(true);
      } else {
        setIsLoading(false), setIsLogged(false);
      }
    });
  }, []);

  const doLogout = async () => {
---- LOGOUT CODE 
}
const doLogin = async () => {
----- LOGIN CODE and UPDATE of state and asyncstorage
}
return (
    <NavigationContainer>
      <AppStack.Navigator initialRouteName="Login">
        <AppStack.Screen name="Login" component={Login} />
        <AppStack.Screen
          name="Home"
          component={Home}
          options={{ headerShown: false }}
        />
      </AppStack.Navigator>
    </NavigationContainer>
  );

Login.js

const Login = ({ loggingIn, userProfile }) => {
  console.log(userProfile);
  return (
    <View style={styles.container}>
      <Button
        title="Login to Site"
        onPress={() => doLogin()}
        disabled={loggingIn}
      >
        {userProfile && userProfile.name} Login to Site
      </Button>
    </View>
  );
};

如何访问 loggingIn(甚至 userProfile)和 doLogin() 函数 我在 App.js 中设置和创建(和更新)?对于像这样的简单用途,应该有一种简单的方法(除了 useContext)。

【问题讨论】:

    标签: react-native react-navigation use-context


    【解决方案1】:

    您可以将参数传递给路由。请参阅此处的第一部分:

    https://reactnavigation.org/docs/params/

    但您可能希望将状态移动到其相关的屏幕组件或其他反应组件。然后,在父组件中,将值传递给子组件。请参阅下面的 TestComponent.js。然后,在子组件中,我们可以使用从父组件传入的 props。请参阅下面的 TestChildComponent.js。

    我还提供了 App.js、TestNavigator.js 和 TestScreen.js,所以你可以复制/粘贴它们并自己测试。

    另外,如果您发现自己使用 useState 钩子管理的状态太多,那么您可以考虑使用 Redux 来代替 useState 钩子进行状态管理。


    代码如下:


    TestComponent.js:

    import React, {useState} from "react";
    import {View, StyleSheet} from "react-native";
    import ChildComponent from "./TestChildComponent";
    
    const TestComponent = props => {
        const [value, setValue] = useState("Bilbo");
    
        return (
            <View style={styles.container}>
                <ChildComponent value={value} setValue={setValue} />
            </View>
        );
    };
    
    
    
    const styles = StyleSheet.create({
        container: {
            flex: 1,
            margin: 100,
        },
    });
    
    export default TestComponent;
    

    TestChildComponent.js:

    import React from "react";
    import {StyleSheet, Text, Button, View} from "react-native";
    
    const ChildComponent = props => {
    
        const buttonPressHandler = () => {
            props.setValue("Frodo");
        };
    
        return (
            <View style={styles.child}>
                <Text>Press Me:</Text>
                <Button title={props.value} onPress={buttonPressHandler} />
            </View>
        );
    };
    
    export default ChildComponent;
    
    const styles = StyleSheet.create({
        child: {
            flexDirection: "row",
            marginHorizontal: 25,
            justifyContent: "center",
            alignItems: "center",
        },
    });
    

    TestNavigator.js:

    import React from "react";
    import {createStackNavigator} from "@react-navigation/stack";
    
    import TestScreen from "./TestScreen";
    
    const TestStackNavigator = createStackNavigator();
    
    export const TestNavigator = () => {
    
        return (
            <TestStackNavigator.Navigator>
                <TestStackNavigator.Screen name={"Test"} component={TestScreen}/>
            </TestStackNavigator.Navigator>
        );
    };
    

    App.js

    import React from 'react';
    import {StyleSheet, SafeAreaView} from 'react-native';
    import {NavigationContainer} from "@react-navigation/native";
    
    import {TestNavigator} from "./TestNavigator";
    
    export default function App() {
    
        return (
            <NavigationContainer>
                <SafeAreaView style={styles.safeAreaView}>
                    <TestNavigator />
                </SafeAreaView>
            </NavigationContainer>
        );
    }
    
    const styles = StyleSheet.create({
        safeAreaView: {
            flex: 1,
        }
    });
    

    TestScreen.js

    import React from "react";
    import TestComponent from "./TestComponent";
    
    const TestScreen = props => {
    
        return (
            <TestComponent />
        );
    };
    
    export default TestScreen;
    

    【讨论】:

    • 谢谢您,您的解决方案当然应该有效,但是要使用此解决方案构建一个 3 文件应用程序(app.js login.js home.js),我将嵌套 5 个文件!此时我可以使用上下文,并保持 3 个文件结构,在上下文中添加状态和函数,并在孩子内部从上下文中获取我需要的内容
    • 没问题,为什么不能有超过 3 个文件?此外,您可以查看此链接:reactnavigation.org/docs/params。第一部分将向您展示如何将参数传递给路由。
    • 好吧,我不想要超过 3 个文件,我只是为一节课制作原型,如果我开始移动,我想留在主题上(使用 api 登录)周围的东西(上下文,redux)它会变得太分散,无论如何我用上下文解决了,尽可能少的占用空间
    猜你喜欢
    • 2018-12-30
    • 2018-02-19
    • 1970-01-01
    • 2019-09-29
    • 2021-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    相关资源
    最近更新 更多