繁体   English   中英

在组件中使用 React 上下文

[英]Using React context in a component

假设我创建了一个简单的 React 上下文来检查我是否已连接

import NetInfo, { NetInfoState } from '@react-native-community/netinfo';
import Constants, { AppOwnership } from 'expo-constants';
import React, { PropsWithChildren, createContext, useContext, useEffect, useState } from 'react';
import { Platform } from 'react-native';

const ConnectionContext = createContext<boolean>(undefined);

export function ConnectionProvider({ children }: PropsWithChildren<any>): JSX.Element {
  const [connected, setConnected] = useState(false);

  function handleConnectionChange(netInfo: NetInfoState) {
    setConnected(
      (Platform.OS === 'ios' && Constants.appOwnership === AppOwnership.Expo) ||
        (netInfo.isConnected && (netInfo.isInternetReachable ?? true))
    );
  }

  useEffect(() => {
    const subscriptionCancel = NetInfo.addEventListener(handleConnectionChange);
    return () => subscriptionCancel();
  }, []);

  return <ConnectionContext.Provider value={connected}>{children}</ConnectionContext.Provider>;
}

export function useConnection() {
  return useContext(ConnectionContext);
}

我想知道我是否想在我现有的组件XYZ使用它,是否有比以下更迂回的方法

从:

export function XYZ() {
   ...xyz code...
}

至:

export function XYZ() {
  return (
    <ConnectionContextProvider>
      <RealXyz>
    </ConnectionContextProvider>
  );
}
function RealXyz() {
  const connected = useConnection();
  ...xyz code...
}

我不认为上下文真的是必要的,因为连接更像是一种单例类型的东西。 下面的代码应该在它自己的文件中,你可以在你的应用程序的任何地方导入这个钩子。

let _isConnected = false;

export const useConnection = () => {
  const [isConnected, setConnected] = useState(_isConnected);

  useEffect(() => {
    function handleConnectionChange(netInfo: NetInfoState) {
      _isConnected =  (Platform.OS === 'ios' && Constants.appOwnership === AppOwnership.Expo) ||
        (netInfo.isConnected && (netInfo.isInternetReachable ?? true))
      
      setConnected(_isConnected);
    }
    
    const subscriptionCancel = NetInfo.addEventListener(handleConnectionChange);

    return () => subscriptionCancel();
  }, []);

  return isConnected;
}

解释:

假设您有两个使用此钩子的组件。 当您的应用程序首次呈现时,只会安装 ComponentA。 一段时间后,连接状态更改为true 然后一段时间后安装 ComponentB。 我们希望 ComponentB 知道连接状态当前为true ,这就是我们使用单例模式(例如私有全局变量_isConnected )的原因。 有多个事件侦听器并不重要,因为它们很便宜并且在卸载组件时会被删除。

如果您有需要在多个组件之间共享的数据,并且您不想通过 props 将其传递到树中,则 Context 很方便。

文档

Context 提供了一种通过组件树传递数据的方法,而无需在每个级别手动向下传递 props。

在您的示例中,我将使用useState ,但是为了让您了解可以选择上下文检查以下代码段的位置:

...

function ABC() {
  const connected = useConnection();
  ...abc code...
}

function ABCParent() {
  return <ABC />
}

...

function XYZ() {
  const connected = useConnection();
  ...xyz code...
}

function XYZParent() {
  return <XYZ />
}

...

function App() {
 return (
  <ConnectionContextProvider>
    <ABCParent />
    <XYZParent />
  </ConnectionContextProvider>
 )
}

使用上下文的两个组件在树的“深处”和单独的分支中。 这个例子有点简单,你可以很容易地通过 props 传递你需要的数据,并且仍然有一个可维护的代码库。

但最终,如果您觉得您的数据模型可以是“全局的”,并且您在单独的分支或多个级别的同一分支中有足够的依赖项,请使用上下文 API。

我发现使用上下文 API 有用的一些数据模型示例是主题、应用程序设置、路由和翻译。

需要注意的一件事:依赖于上下文的组件的可重用性将降低(这在项目之间更相关),有时您可以选择组合而不是使用上下文 API。 查看文档的使用前上下文部分以获取有关此内容的更多信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM