[解決済み] Context APIを使用しようとすると「renderは関数ではありません」と表示される
質問
私はContext APIを学ぼうとしています。私が実現したいことは、ログインしたユーザーをヘッダーに表示し、ログイン状態に基づいてメニューオプションを操作することです(stateに'isAuthenticated'を保存することは安全ですか)。
私のコンテキストクラス。
import React from 'react';
const Context = React.createContext();
export class Provider extends React.Component {
state = {
isAuthenticated: true,
user: {
name: "Joe Smith",
email: "[email protected]"
}
}
render() {
return (
<Context.Provider value={this.state}>
{this.props.children}
</Context.Provider>
)
}
}
export const Consumer = Context.Consumer;
というわけで、極めて基本的なものです。状態を設定し、後の子コンポーネントでチャップスの名前を表示したいと思います。
私のApp.jsは、すべてのコンポーネントがこのデータにアクセスできるように、'Provider'を使用しています。
import React from 'react';
import { HashRouter , Route, Switch } from 'react-router-dom';
import Home from './components/home';
import Header from './components/header';
import Accounts from './components/accounts';
import Reports from './components/reports';
import Login from './components/login';
import {Container} from 'reactstrap';
import { Provider } from './context';
function App() {
return (
<div className="App">
<Provider>
<HashRouter>
<Header />
<Container>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/accounts" component={Accounts} />
<Route exact path="/reports" component={Reports} />
<Route exact path="/login" component={Login} />
</Switch>
</Container>
</HashRouter>
</Provider>
</div>
);
}
export default App;
この場合、'Header'は私のコンテキストにアクセスする必要があるわけです。 Headerにはメニューが表示されます(コンテキストに追加した情報に基づいて、オプションやログインボタンなどの表示/非表示を切り替えます)。
メニューの下には、小さな情報バーを表示したい。例えば、ログインしているユーザー名などです。そこで、私のヘッダー・クラスは次のようになります。
import React from 'react';
import Menu from './menu';
import InfoBar from './infobar';
import { Consumer } from '../context';
class Header extends React.Component {
render() {
const menuStyle = {
paddingBottom: "5px"
}
return(
<Consumer>
<div style={menuStyle}>
{value => {
console.log(value);
return (
<h1>Test</h1>
)
}}
<Menu />
<InfoBar />
</div>
</Consumer>
)
}
}
export default Header;
しかし、今度は問題が起こります。私のコードを実行すると、コンパイルして実行されるのですが、すぐにランタイムエラーが発生するのです。
TypeError: render is not a function updateContextConsumer C:/Storage/Scratch/ReactApp/accufinance/node_modules/react-dom/cjs/react-dom.development.js:16082
リターンと複数の子について何かで読みましたが、私のコードにはその問題がないようです。この問題を理解し、どこで問題が起きているのかを理解するための支援があれば、とても助かります。header'のコードをコメントアウトすると、エラーは出ませんが......画面も出ません。この辺りで発生しているようです。
解決方法は?
Context Consumer はレンダープロップ、具体的には関数を子コンポーネントとして使用するため、その直下の子コンポーネントが(コンポーネントではなく)関数であることが期待されます。あなたの場合、div を関数の中に移動させればよいのです。
<Consumer>
{value => {
console.log(value);
return (
<div style={menuStyle}>
<h1>Test</h1>
<Menu />
<InfoBar />
</div>
)
}}
</Consumer>
Render Props は、コンポーネントの内部状態を子コンポーネントに公開したいが、異なるタイプの子コンポーネントでも使用したい場合に、非常に強力です。
このようなパターンです。
class Parent extends Component {
state = { name: 'Mike' }
handleChange = (e) => this.setState({ name: e.target.value })
render() {
// Here's the main difference: We expect `children` to be
// a function, and we pass name in as the argument
return children(state.name);
}
}
const InputChild = props => <input value={props.name} />
const HeaderChild = props => <h1>{props.name}</h1>
const App = () => {
return (
<Parent>
{name => {
// We could easily swap in `HeaderChild` here (or
// anything else!), passing `Parent`'s internal
// state.name to it instead:
<InputChild name={name} />
}
</Parent>
)
}
これはContextを機能させるもので、Consumerは子コンポーネントに関する知識を一切持っていませんが、その状態(Providerからの値)を公開することができます。
Reactのドキュメントには、レンダー・プロップスに関する素晴らしいセクションがあります。 https://reactjs.org/docs/render-props.html
関連
-
[解決済み】Failed to load resource: net::ERR_FILE_NOT_FOUND loading json.js
-
[解決済み] Uncaught Invariant Violation: 前のレンダリング中よりも多くのフックをレンダリングした
-
[解決済み] エラー。モジュールhtmlが見つからない
-
[解決済み】Vueのテンプレートまたはレンダー関数が定義されていない 私はどちらも使っていないのですが?
-
[解決済み] Node.jsを使うタイミングをどう判断するか?
-
[解決済み] JavaScriptで二重引用符と単一引用符はいつ使うべきですか?
-
[解決済み] varキーワードの目的と、どのような場合に使用する(または省略する)べきですか?
-
[解決済み] encodeURI / encodeURIComponentの代わりにescapeを使用するのはどのような場合ですか?
-
[解決済み] JSLintが突然レポートする。"use strict" の関数形式を使用する
-
[解決済み】JavaScriptの関数名を文字列で指定して実行する方法
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】node.js TypeError: path must be absolute or specify root to res.sendFile [JSONのパースに失敗しました]。
-
[解決済み】Angular JS Uncaught Error。[インジェクター:モジュラー]。
-
[解決済み】webpack: モジュールが見つかりません。Error: 解決できない(相対パスで)
-
[解決済み] React with ES7: Uncaught TypeError: Cannot read property 'state' of undefined [duplicate] (未定義のプロパティ'state'を読み込むことはできません。
-
[解決済み】未定義のプロパティ 'bind' を読み込めない。React.js【重複あり
-
[解決済み】React、Uncaught ReferenceError。ReactDOMは定義されていません
-
[解決済み】WebpackとBabelで「このファイルタイプを扱うには適切なローダーが必要な場合があります。
-
[解決済み】Uncaught SyntaxError: JSON の位置 0 に予期しないトークン u があります。
-
[解決済み】このオブジェクトの "forEach "はなぜ関数でないのですか?
-
[解決済み] [Solved] Uncaught Invariant Violation: 前のレンダリング中よりも多くのフックをレンダリングする