16

我有一个我正在使用 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. 有没有更好的方法在 App.js 中使用多个上下文提供程序。
  2. 这些提供者的嵌套顺序对 App 有影响吗?
  3. 我们可以跳过添加提供程序<App/>,而是将它们导入任何需要它的屏幕并将该屏幕元素包装在其中吗?
4

4 回答 4

10

我不会按被问到的顺序回答。

答案 3

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

原因是无论何时更新提供者,每个消费者都会重新渲染,你不能不使用或React.memo停止它。你不应该过度使用上下文ReactPureComponentshouldComponentUpdate

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 可以是这个问题的答案,在正确的位置使用上下文(对于仅使用上下文的组件。不要在 App 级别随机每个上下文)。如果您的上下文经常更新,我建议不要使用其他方式,以便您可以使用React.memoorPureComponentshouldComponentUpdate来防止不必要的重新渲染以优化性能。

答案 2

该订单不会影响应用程序。

于 2020-06-30T04:00:04.050 回答
1

答案

答案1:

  1. 没有更好的方法来添加应用程序级别的提供程序,但某些提供程序没有上下文应用程序级别的平均值(我们不需要到处都有应用程序内上下文)。一些提供程序具有模块级别。所以你可以包裹在一个特定的树或组件之外
const UserScreen = () => (
  <UserProvider>
    <UserScreen />
  <UserProvider />
)

答案 2:

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

答案 3:

  1. 是的,如果提供程序不是应用程序级别的,我们可以跳过提供程序,App.js这意味着我们在应用程序中不需要上下文。如果我们需要一个或两个屏幕或一棵树中的上下文,那么我们可以将该屏幕或树包装在提供程序中而不使用 inApp.js
于 2020-06-27T10:56:53.527 回答
1
  1. 我不确定你所说的“更好”是什么意思。如果你只是想清理你的 App 组件,你可以将Provider渲染抽象成一个单独的函数。可能会帮助您根据需要完成它

  2. 如果像您的示例一样,您将整个应用程序与 all 一起包装Providers并且它们彼此独立,那么顺序无关紧要。否则,它们的行为与其他组件没有什么不同,只有子组件可以访问其数据并且数据流是单向的。

  3. 是的,无需为您的整个应用程序提供所有数据。

于 2020-06-27T10:59:12.217 回答
0
  1. 有没有更好的方法在 App.js 中使用多个上下文提供程序。

答案:是的

  • 您可以使用任何数字Context Providers来包裹您的App.,但请确保这些数据Providers不应该经常更新,并且它们被视为全局状态,这意味着它们可以从应用程序中的任何位置访问或将被访问。例如:您的应用主题、身份验证状态、用户个人资料、...
  • 如果数据被认为是特定的用例,只在你的几个地方App使用,你不应该使用Context Provider,因为如果数据被更新,它的所有孩子都被迫重新渲染,不管你使用任何 React API 来防止它喜欢React.memo。参考这个
  1. 这些provider的嵌套顺序对App有影响吗

答案:是的

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

答:这取决于您的用例。

于 2020-07-02T08:13:34.487 回答