首页 > 解决方案 > 使用 React Native 中的 React Navigation 将状态从主 App.js 传递到屏幕组件

问题描述

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

这是我的代码的一部分:

应用程序.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>
  );

登录.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>
  );
};

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

标签: react-nativereact-navigationuse-context

解决方案


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

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

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

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

此外,如果您发现自己使用 useState 挂钩管理的状态太多,那么您可以考虑使用Redux进行状态管理,而不是使用 useState 挂钩。


下面的代码:


测试组件.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",
    },
});

测试导航器.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>
    );
};

应用程序.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,
    }
});

测试屏幕.js

import React from "react";
import TestComponent from "./TestComponent";

const TestScreen = props => {

    return (
        <TestComponent />
    );
};

export default TestScreen;

推荐阅读