【问题标题】:How to listen to navigation state params changes in React Native?如何在 React Native 中监听导航状态参数的变化?
【发布时间】:2020-09-08 23:34:21
【问题描述】:

我正在使用 React Native 开发一个移动应用程序。在那里,我在导航到第二页时传递了一些东西。

所以,假设我的第一个屏幕是这样的。

export default function firstScreen(props) {
  return(
    //data is a custom object variable that may be changed.
    <Button onPress={() => props.navigation.navigate('SecondScreen', { data: data } )} /> 
  )
}

在我的第二个屏幕上,假设有这样的东西......

export default function secondScreen(props) {
  const { data } = props.navigation.state.params;

  useEffect(() => {
    console.log(data);
  }, [data])


  return(
    //content
  )
}

我的问题是,当data 从第一个屏幕更改时,第二个屏幕不会监听该更改并在控制台上打印data 变量的内容。

所以,我想知道,如何在 React Native 中监听导航状态的变化。

【问题讨论】:

    标签: javascript react-native navigation state use-effect


    【解决方案1】:

    以下是我在 React Navigation V5 中使用 hooks 解决此问题的方法:

    import { useRoute } from '@react-navigation/native';
    const route = useRoute();
    useEffect(() => { //This will run whenever params change
         const {params = {}} = route;
        //your logic here
    }, [route]);
    

    【讨论】:

    • 不适用于相同的 openURL 、相同的屏幕、不同的参数
    【解决方案2】:

    您可以使用钩子“useNavigationState”从第二个屏幕获取导航状态。

    然后,您将再次遇到从第一个屏幕实际更新它的问题。 当您传递参数时,它是导航状态的一部分,并且您对对象所做的更改不会反映在那里。

    更新导航状态的一种方法是分派一个动作,但这将是一个问题,因为您需要找到要更新的屏幕的键。 调度会是这样的

    navigation.dispatch({ ...CommonActions.setParams({ data: {} }), 来源:route.key, });

    由于您需要将对象的更新更新到另一个屏幕,您应该考虑诸如反应上下文之类的东西,或者如果您的应用中已经有 redux,您可以在需要时使用它。

    最简单的方法是反应上下文,您可以从一个屏幕更新并从另一个屏幕接收。

    使用上下文的版本如下所示。 这里使用了一个简单的堆栈导航器,上下文从主屏幕更新,值可以从设置屏幕读取。您可以使用相同的方式更新数据变量并从另一个屏幕获取数据。这里我们不使用导航状态,但我们为变量维护自己的上下文。

    const Stack = createStackNavigator();
    const CountContext = React.createContext({ count: 1, setCount: () => {} });
    
    function HomeScreen({ navigation, route }) {
      const { count, setCount } = React.useContext(CountContext);
      React.useEffect(() => {
        const interval = setInterval(() => {
          setCount(count => count + 1);
        }, 1000);
    
        return () => {
          clearInterval(interval);
        };
      }, []);
    
      return (
        <View>
          <Text>Test{count}</Text>
          <Button
            title="Go to settings"
            onPress={() => navigation.navigate('Settings')}
          />
        </View>
      );
    }
    
    function SettingsScreen({ navigation, route }) {
      const { count, setCount } = React.useContext(CountContext);
      return (
        <View>
          <Text>Settings! {count}</Text>
          <Button title="Go back" onPress={() => navigation.goBack()} />
        </View>
      );
    }
    
    export default function App() {
      const [count, setCount] = React.useState(0);
      const value = { count, setCount };
    
      return (
        <CountContext.Provider value={value}>
          <NavigationContainer>
            <Stack.Navigator>
              <Stack.Screen name="Home" component={HomeScreen} />
              <Stack.Screen name="Settings" component={SettingsScreen} />
            </Stack.Navigator>
          </NavigationContainer>
        </CountContext.Provider>
      );
    }
    

    你可以看看这个小吃 https://snack.expo.io/@guruparan/stateparamschange

    【讨论】:

    • 感谢您的回答。顺便说一句,我想在 React NATIVE 中做到这一点。不在 React JS 中。你能帮我在 React NATIVE 中做到这一点吗?
    • 这是为了反应原生,如果你愿意,我可以用上下文代码更新答案
    • 是的,请...您能否使用完整的示例代码更新答案?这对我帮助很大。
    • 非常感谢您的帮助和解答!! :-) 效果很好!!它还帮助我获得了通过 Context API 使用全局状态的知识。
    • 如果你已经使用了状态管理工具,那为什么还要在你的导航参数中传递数据呢?从您的状态管理工具(上下文或 redux)中获取第二个屏幕中的数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    • 2014-12-11
    • 1970-01-01
    • 1970-01-01
    • 2017-05-31
    • 2015-05-23
    相关资源
    最近更新 更多