代码之家  ›  专栏  ›  技术社区  ›  esafwan

在ReactNative中使用多个上下文提供程序的更好方法

  •  0
  • esafwan  · 技术社区  · 6 年前

    我有一个应用程序,我在其中使用3 Context Provider 。为了使应用程序工作,我必须包装 <App/> 在所有这些 providers 。随着我的应用程序的增长,我希望有更多的提供商来提供我必须连接的更多类型的数据。我已经开始觉得,可能有更好的方法让供应商进入 <App /> .

    我的 App.js 代码:

    import React from 'react';
    import { createStackNavigator } from 'react-navigation-stack';
    import { createAppContainer } from 'react-navigation';
    import { Provider as BlogProvider} from './src/context/BlogContext';
    import { Provider as VehicleProvider} from './src/context/VehicleContext';
    import { Provider as AuthProvider} from './src/context/AuthContext';
    
    import IndexScreen from './src/screens/IndexScreen';
    import ShowScreen from './src/screens/ShowScreen';
    import CreateScreen from './src/screens/CreateScreen';
    import EditScreen from './src/screens/EditScreen';
    import VehicleScreen from './src/screens/VehicleScreen';
    
    const navigator = createStackNavigator(
      {
        Index: IndexScreen,
        Show: ShowScreen,
        Create: CreateScreen,
        Edit: EditScreen,
        Debug: DebugScreen,
        Vehicle: VehicleScreen,
    
      },
      {
        initialRouteName: 'Index',
        defaultNavigationOptions: {
          title: 'Main'
        }
      }
    );
    
    const App = createAppContainer(navigator);
    
    export default () => {
      return (
        <BlogProvider>
          <VehicleProvider>
            <AuthProvider>
                 <App />
            </AuthProvider>
          </VehicleProvider>
        </BlogProvider>
      );
    };
    

    我的一些问题是:

    1. 是否有更好的方法在应用程序中使用多个上下文提供程序。
    2. 这些提供者的嵌套顺序对应用程序有任何影响吗?
    3. 我们可以跳过添加提供者吗 <应用程序/> 而是将它们导入到需要的任何屏幕中,并将该屏幕元素包裹在其中?
    0 回复  |  直到 5 年前
        1
  •  14
  •   Audwin Oyong Kuldeep Bora    5 年前

    我不会按顺序回答。

    答案3

    如果提供程序仅提供特定组件的上下文,则应在该组件中导入并使用它。 不要 包 App 用它。

    原因是每当提供者更新时,每个消费者都会重新呈现,你不能没有用 React.memo 或 ReactPureComponent 或 shouldComponentUpdate 阻止它。 You should not overuse context

    const Root = () => {
      return (
        <AppProvider>
          <ComponentProvider>
            <App/>
          <ComponentProvider>
        </AppProvider>
      )
    }
    
    const App = () => {
      return (
        <>
          <ComponentA/>
          <ComponentB/>
        <>
      )
    }
    
    const ComponentContext = createContext()
    const ComponentProvider = ({ children }) => {
      // If any value here is updated --> all consumer will be render
      // --> App re-render --> ComponentA and ComponentB re-render
      return (
        <ComponentContext.Provider value={{ value1, value2, value }}>
          {children}
        </ComponentContext.Provider>
      )
    }
    

    你应该这样做

    const Root = () => {
      <AppProvider>
        <App/>
      </AppProvider>
    }
    
    const App = () => {
      return (
       <>
        <ComponentA/>
        <ComponentB/>
       <>
      )
    }
    
    const ComponentA = () => {
      return (
        <ComponentProvider>
          <OtherComponent/>
        <ComponentProvider>
       )
    }
    
    const ComponentContext = createContext()
    const ComponentProvider = ({ children }) => {
      // If any value here is updated --> all consumer (ComponentA only) will be render
      return (
        <ComponentContext.Provider value={{ value1, value2, value3 }}>
          {children}
        </ComponenContext.Provider>
      )
    }
    

    答案1

    答案3可能是这个问题的答案,在正确的地方使用上下文(对于只使用上下文的组件。不要在应用程序级别随机使用每个上下文)。如果你的上下文经常更新,我建议不要使用 other ways 所以你可以使用 React.memo 或 PureComponent 或 should组件更新 以防止不必要的重新渲染,从而优化性能。

    答案2

    该命令不会影响应用程序。

        2
  •  1
  •   hotpink    6 年前
    1. 我不知道你说的“更好”是什么意思。如果你只是想清理你的应用程序组件,你可以抽象 Provider 渲染成一个单独的函数。 This 或 this 可能会帮助你根据需要完成它

    2. 如果像你的例子一样,你用所有 Providers 它们彼此独立,那么顺序就无关紧要了。否则,它们的行为与其他组件没有什么不同,只有子组件可以访问其数据,数据流是单向的。

    3. 是的,不需要向整个应用程序提供所有数据。

        3
  •  1
  •   Trung Nguyen    6 年前
    1. 是否有更好的方法在应用程序中使用多个上下文提供程序。

    答案:是

    • 你可以用任何数字 Context Providers 围绕着你 App ,但要确保这些数据 Providers 不应频繁更新,它们被视为全局状态,这意味着它们可以从应用程序中的任何地方访问或将被访问。例如:你的应用主题、身份验证状态、用户资料,。。。
    • 如果数据被视为仅在您的数据库中的少数地方使用的特定用例 应用程序 ,你不应该使用 Context Provider ,因为如果数据被更新,它的所有孩子都会被迫重新渲染,不管你使用任何React API来防止它,就像 React.memo 。请参阅 this
    1. 这些提供者的嵌套顺序对应用程序有任何影响吗

    答案:是

    • 正如我在回答1中所说,如果 Provider 如果频繁更新的数据是更新频率较低的数据的父数据,它将影响其所有子数据,因此您可以通过将更新频率最低的最外层包裹为父数据来进行重构。
    1. 我们可以跳过添加提供者,而是将它们导入到需要的任何屏幕中,并将该屏幕元素包裹在其中吗?

    答:这取决于你的用例。

        4
  •  1
  •   Audwin Oyong Kuldeep Bora    5 年前

    答案

    答案1:

    1. 没有更好的方法来添加应用程序级提供者,但有些提供者没有上下文应用程序级手段(我们不需要无处不在的应用程序中的上下文)。某些提供商具有模块级别。因此,您可以将其包裹在特定树或组件的外部
    const UserScreen = () => (
      <UserProvider>
        <UserScreen />
      <UserProvider />
    )
    

    答案2:

    1. 在工作中没有效果,但有时我们需要从父函数调用子函数,因此,我们需要使用 ref 在这个嵌套的级别提供程序中,我们必须使用 forwardRef 其余的事情都很好。

    答案3:

    1. 是的,我们可以跳过提供者 App.js 如果该提供者不是应用程序级别的,则意味着我们不需要应用程序中的所有地方都有上下文。如果我们需要一个或两个屏幕或一棵树中的上下文,那么我们可以将该屏幕或树包装在提供者中,而不在 App.js