web-dev-qa-db-ja.com

React Nativeで複数のコンテキストプロバイダーを使用するためのより良い方法

3 Context Providerを使用しているアプリがあります。アプリが機能するためには、これらすべてのproviders<App/>をラップする必要があります。アプリが成長するにつれ、接続する必要のあるより多くの種類のデータを提供するプロバイダーがいくつか追加されることを期待しています。私はすでにプロバイダーを<App />に渡すより良い方法があるかもしれないと感じ始めました。

My 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. <App/>へのプロバイダーの追加をスキップして、代わりに、必要な任意の画面にプロバイダーをインポートし、その画面要素をラップできますか?
7
esafwan

頼まれた順序ではお答えしません。

回答3

プロバイダーが特定のコンポーネントのコンテキストのみを提供する場合は、そのコンポーネントにインポートして使用する必要があります。 しないでくださいAppで囲みます。

その理由は、プロバイダーが更新されるたびに、すべてのコンシューマーが再レンダリングされるため、使用できないことですReact.memoまたはReactPureComponentまたはshouldComponentUpdateで停止します。 コンテキストを使いすぎないでください

const Root =() =>{
  return(
    <AppProvider>
      <ComponenAtProvider>
       <App/>
     <ComponenAtProvider>
    </AppProvider>
  )
}

const App =() =>{
  return(
    <>
      <ComponentA/>
      <ComponentB/>
    <>
  )
}

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

代わりにこれを行う必要があります

const Root =() =>{
  <AppProvider>
      <App/>
  </AppProvider>
}

const App =() =>{
  return(
   <>
    <ComponentA/>
    <ComponentB/>
   <>
  )
}

const ComponentA = () =>{
  return(
    <ComponenAtProvider>
      <App/>
    <ComponenAtProvider>
   )
}

const  ComponenAContext = createContext()
const ComponenAtProvider = ({children}) =>{
  // If any value here is updated ==> all consumer (ComponentA only) will be render
  return(
    <ComponenAContext.Provider value={{value1, value2, valu3}}>
      {children}
    </ComponenAContext.Provider>
  )
}

Answer1

答え3はこれに対する答えになる可能性があります。適切な場所でコンテキストを使用します(コンテキストのみを消費するコンポーネントの場合。アプリレベルですべてのコンテキストをランダムにしないでください)。コンテキストが頻繁に更新される場合は、 その他の方法 を使用しないことをお勧めします。これにより、React.memoまたはPureComponentまたはshouldComponentUpdateは、不要な再レンダリングを防止してパフォーマンスを最適化します。

Answer2

注文はアプリに影響しません

1
Tony Nguyen

答え

回答1:

  1. アプリレベルのプロバイダーを追加するより良い方法はありませんが、一部のプロバイダーにはコンテキストアプリレベルの平均値がありません(どこにでもアプリ内コンテキストが必要なわけではありません)。一部のプロバイダーにはモジュールレベルがあります。特定のツリーまたはコンポーネントの外側をラップすることができます
const UserScreen=()=>(
<UserProvider>
  <UserScreen />
<UserProvider />
)

回答2:

  1. 動作しても効果はありませんが、親から子関数を呼び出す必要がある場合があるため、refを使用する必要があります。このネストされたレベルのプロバイダーでは、forwardRefを使用する必要があります。残りはうまくいきます

回答3:

  1. はい。App.jsのプロバイダーがアプリレベルでない場合、そのプロバイダーをスキップできます。つまり、アプリ内のすべての場所でコンテキストが必要になるわけではありません。 1つまたは2つの画面または1つのツリーでコンテキストが必要な場合は、その画面またはツリーをプロバイダーでラップし、app.jsでは使用しないでください。
2
Muhammad Numan
  1. あなたが「より良い」とはどういう意味かわかりません。 Appコンポーネントをクリーンアップしたいだけの場合は、Providerレンダリングを別の関数に抽象化できます。 This または this は、ニーズに応じてそれを達成するのに役立つ場合があります

  2. 例のように、アプリケーション全体をすべてのProvidersでラップし、それらが互いに独立している場合、順序は重要ではありません。それ以外の場合は、他のコンポーネントと同じように動作し、子だけがデータにアクセスでき、データフローは単方向です。

  3. はい、アプリケーション全体にすべてのデータを提供する必要はありません。

1
hotpink
  1. アプリで複数のコンテキストプロバイダーを使用するより良い方法はありますか?.

回答:はい

  • Appを囲むために任意の数Context Providersを使用できますが、それらのProvidersのデータは頻繁に更新されず、グローバル状態として扱われることを確認してください。アプリ内のどこからでもアクセスできます。例:アプリのテーマ、認証ステータス、ユーザーのプロファイル、...
  • データがAppのごく一部でのみ使用される特定のユースケースと見なされる場合、Context Providerを使用しないでください。データが更新されると、すべての子が強制的に再実行されます。 React React.memoのようなAPIを回避するためのAPIを使用するかどうかに関係なく、レンダリングします。 this を参照してください。
  1. これらのプロバイダーがネストされている順序はアプリに影響しますか

回答:はい

  • 回答1で述べたように、頻繁に更新されるデータがProviderにあり、更新頻度が低いデータの親である場合、すべての子に影響を与えるため、最も更新されていない最外部を次のようにラップしてリファクタリングできます。親。
  1. プロバイダーの追加をスキップして、必要な任意の画面にプロバイダーをインポートし、その画面要素をラップすることはできますか?

回答:ユースケース次第です。

0
Trung Nguyen