[解決済み] 子コンポーネントの内部からReact Contextを更新するにはどうすればよいですか?
質問
コンテキストに以下のような言語設定があります。
class LanguageProvider extends Component {
static childContextTypes = {
langConfig: PropTypes.object,
};
getChildContext() {
return { langConfig: 'en' };
}
render() {
return this.props.children;
}
}
export default LanguageProvider;
私のアプリケーションコードは以下のようなものになります。
<LanguageProvider>
<App>
<MyPage />
</App>
</LanguageProvider>
私のページには、言語を切り替えるコンポーネントがあります。
<MyPage>
<LanguageSwitcher/>
</MyPage>
LanguageSwitcher
この中で
MyPage
のように言語を'jp'に変更するために、コンテキストを更新する必要があります。
class LanguageSwitcher extends Component {
static contextTypes = {
langConfig: PropTypes.object,
};
updateLanguage() {
//Here I need to update the langConfig to 'jp'
}
render() {
return <button onClick={this.updateLanguage}>Change Language</button>;
}
}
export default LanguageSwitcher;
LanguageSwitcherコンポーネントの内部からコンテキストを更新するには?
解決方法は?
フックを使用する
フックは 16.8.0 で導入されました。したがって、以下のコードには最低でも 16.8.0 が必要です (クラスコンポーネントの例については下にスクロールしてください)。 CodeSandboxデモ
1. 動的コンテキストの親状態の設定
まず、コンシューマに渡す動的なコンテキストを用意するために、親の状態を使うことにする。こうすることで、単一の真実のソースを確保することができる。例えば、親アプリは次のようになる。
const App = () => {
const [language, setLanguage] = useState("en");
const value = { language, setLanguage };
return (
...
);
};
は
language
が格納されている状態です。の両方を渡します。
language
とセッター関数
setLanguage
は、後でコンテキストを経由して
2. コンテキストの作成
次に、このような言語コンテキストを作成しました。
// set the defaults
const LanguageContext = React.createContext({
language: "en",
setLanguage: () => {}
});
ここでは
language
('en') と
setLanguage
この関数は、コンテキストプロバイダからコンシューマに送信されます。これらはあくまでデフォルトであり、親コンポーネントでプロバイダコンポーネントを使用する際にその値を提供することになります。
App
.
注
LanguageContext
は、フックを使ってもクラスベースのコンポーネントを使っても同じです。
3. コンテキストコンシューマの作成
言語スイッチャーに言語を設定させるためには、コンテキストを介して言語セッター関数にアクセスできる必要があります。以下のような感じです.
const LanguageSwitcher = () => {
const { language, setLanguage } = useContext(LanguageContext);
return (
<button onClick={() => setLanguage("jp")}>
Switch Language (Current: {language})
</button>
);
};
ここでは言語を「jp」に設定しているだけですが、独自のロジックで言語を設定することも可能でしょう。
4. プロバイダでコンシューマを包む
ここで、言語スイッチャーコンポーネントを
LanguageContext.Provider
そして、より深いレベルにコンテキストを介して送信される必要がある値を渡します。以下は、私の親である
App
のように見える。
const App = () => {
const [language, setLanguage] = useState("en");
const value = { language, setLanguage };
return (
<LanguageContext.Provider value={value}>
<h2>Current Language: {language}</h2>
<p>Click button to change to jp</p>
<div>
{/* Can be nested */}
<LanguageSwitcher />
</div>
</LanguageContext.Provider>
);
};
これで、言語スイッチャーがクリックされるたびに、コンテキストが動的に更新されるようになりました。
クラスコンポーネントの使用
最新の コンテキストAPI は React 16.3 で導入され、動的なコンテキストを持つための素晴らしい方法を提供します。以下のコードでは、最低でも16.3.0が必要です。 コードサンドボックスデモ
1. 動的コンテキストの親状態の設定
まず、コンシューマに渡す動的なコンテキストを用意するために、親の状態を使うことにする。こうすることで、単一の真実のソースを確保することができる。例えば、親アプリは次のようになる。
class App extends Component {
setLanguage = language => {
this.setState({ language });
};
state = {
language: "en",
setLanguage: this.setLanguage
};
...
}
は
language
は言語セッターメソッドとともにステートに格納されますが、これはステートツリーの外に置いてもかまいません.
2. コンテキストの作成
次に、このような言語コンテキストを作成しました。
// set the defaults
const LanguageContext = React.createContext({
language: "en",
setLanguage: () => {}
});
ここでは
language
('en') と
setLanguage
この関数は、コンテキストプロバイダからコンシューマに送信されます。これらはあくまでデフォルトであり、親コンポーネントでプロバイダコンポーネントを使用する際にその値を提供することになります。
App
.
3. コンテキストコンシューマの作成
言語スイッチャーに言語を設定させるためには、コンテキストを介して言語セッター関数にアクセスできる必要があります。以下のような感じです.
class LanguageSwitcher extends Component {
render() {
return (
<LanguageContext.Consumer>
{({ language, setLanguage }) => (
<button onClick={() => setLanguage("jp")}>
Switch Language (Current: {language})
</button>
)}
</LanguageContext.Consumer>
);
}
}
ここでは言語を「jp」に設定しているだけですが、独自のロジックで言語を設定することも可能でしょう。
4. プロバイダでコンシューマを包む
ここで、言語スイッチャーコンポーネントを
LanguageContext.Provider
そして、より深いレベルにコンテキストを介して送信される必要がある値を渡します。以下は、私の親である
App
のように見える。
class App extends Component {
setLanguage = language => {
this.setState({ language });
};
state = {
language: "en",
setLanguage: this.setLanguage
};
render() {
return (
<LanguageContext.Provider value={this.state}>
<h2>Current Language: {this.state.language}</h2>
<p>Click button to change to jp</p>
<div>
{/* Can be nested */}
<LanguageSwitcher />
</div>
</LanguageContext.Provider>
);
}
}
これで、言語スイッチャーがクリックされるたびに、コンテキストが動的に更新されるようになりました。
関連
-
Vue+ElementUIによる大規模なフォームの処理例
-
[解決済み】SyntaxError: JSONの位置1に予期しないトークンoがある。
-
[解決済み] 配列から特定の項目を削除するにはどうすればよいですか?
-
[解決済み] コールバック内で正しい `this` にアクセスする方法
-
[解決済み] React JSX内のループ
-
[解決済み] setStateを呼び出さずにReactコンポーネントを強制的に再レンダリングすることは可能ですか?
-
[解決済み] Reactコンポーネントに条件付きで属性を追加するにはどうすればよいですか?
-
[解決済み] 親メソッドから子メソッドを呼び出す
-
[解決済み] Reactコンポーネント外でのクリックを検出する
-
[解決済み】Reactの機能的なステートレスコンポーネント、PureComponent、Component、どのような違いがあり、いつ何を使うべきですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
JavaScriptの関数この指摘の問題を説明
-
親子コンポーネント通信を解決する3つのVueスロット
-
Vueでルートネスティングを実装する例
-
[解決済み] 配列の結合時に未定義のプロパティ 'push' を読み込むことができない
-
[解決済み] Web API エラー - このリクエストはブロックされました; コンテンツは HTTPS で提供されなければなりません
-
[解決済み】ExpressJS - throw er Unhandled errorイベント
-
[解決済み】リクエストに失敗していないのに、「TypeError: failed to fetch」が表示される。
-
[解決済み】<select>で現在選択されている<option>をJavaScriptで取得するにはどうすればよいですか?
-
JavaScriptのStringに関する共通メソッド
-
Uncaught TypeError: null のプロパティ 'offsetHeight' を読み取れませんでした。