我在React中看到的新Context API的所有示例都在一个文件中,例如https://github.com/wesbos/React-Context.
当我试图让它在多个文件中工作时,我显然错过了一些东西.
我希望创建一个GlobalConfiguration
组件(MyProvider
下面)在上下文中创建和管理值,为MyConsumer
从中读取的任何子组件(下面)做好准备.
render() {
return (
<MyProvider>
<MyConsumer />
</MyProvider>
);
}
Run Code Online (Sandbox Code Playgroud)
import React, { Component } from 'react';
const MyContext = React.createContext('test');
export default class MyProvider extends Component {
render() {
return (
<MyContext.Provider
value={{ somevalue: 1 }}>
{this.props.children}
</MyContext.Provider >
);
}
}
Run Code Online (Sandbox Code Playgroud)
import React, { Component } from 'react';
const MyContext = React.createContext('test');
export default class MyConsumer extends Component {
render() {
return (
<MyContext.Consumer>
{(context) => (
<div>{context.state.somevalue}</div>
)}
</MyContext.Consumer>
);
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,在控制台中失败了:
consumer.js:12 Uncaught TypeError: Cannot read property 'somevalue' of undefined
我完全错过了这一点吗?是否有文档或示例如何跨多个文件工作?
ant*_*ton 24
我认为您遇到的问题是您正在创建两个不同的上下文,并尝试将它们用作一个上下文.它是Context
通过创建React.createContext
链接Provider
和Consumer
.
制作一个文件(我会称之为configContext.js
)
configContext.js
import React, { Component, createContext } from "react";
// Provider and Consumer are connected through their "parent" context
const { Provider, Consumer } = createContext();
// Provider will be exported wrapped in ConfigProvider component.
class ConfigProvider extends Component {
state = {
userLoggedIn: false, // Mock login
profile: { // Mock user data
username: "Morgan",
image: "https://morganfillman.space/200/200",
bio: "I'm Mogran—so... yeah."
},
toggleLogin: () => {
const setTo = !this.state.userLoggedIn;
this.setState({ userLoggedIn: setTo });
}
};
render() {
return (
<Provider
value={{
userLoggedIn: this.state.userLoggedIn,
profile: this.state.profile,
toggleLogin: this.state.toggleLogin
}}
>
{this.props.children}
</Provider>
);
}
}
export { ConfigProvider };
// I make this default since it will probably be exported most often.
export default Consumer;
Run Code Online (Sandbox Code Playgroud)
index.js
...
// We only import the ConfigProvider, not the Context, Provider, or Consumer.
import { ConfigProvider } from "./configContext";
import Header from "./Header";
import Profile from "./Profile";
import "./styles.css";
function App() {
return (
<div className="App">
<ConfigProvider>
<Header />
<main>
<Profile />
</main>
<footer>...</footer>
</ConfigProvider>
</div>
);
}
...
Run Code Online (Sandbox Code Playgroud)
Header.js
import React from 'react'
import LoginBtn from './LoginBtn'
... // a couple of styles
const Header = props => {
return (
... // Opening tag, etc.
<LoginBtn /> // LoginBtn has access to Context data, see file.
... // etc.
export default Header
Run Code Online (Sandbox Code Playgroud)
LoginBtn.js
import React from "react";
import Consumer from "./configContext";
const LoginBtn = props => {
return (
<Consumer>
{ctx => {
return (
<button className="login-btn" onClick={() => ctx.toggleLogin()}>
{ctx.userLoggedIn ? "Logout" : "Login"}
</button>
);
}}
</Consumer>
);
};
export default LoginBtn;
Run Code Online (Sandbox Code Playgroud)
Profile.js
import React, { Fragment } from "react";
import Consumer from "./configContext"; // Always from that same file.
const UserProfile = props => {...}; // Dumb component
const Welcome = props => {...}; // Dumb component
const Profile = props => {
return (
<Consumer>
...
{ctx.userLoggedIn ? (
<UserProfile profile={ctx.profile} />
) : (<Welcome />)}
...
</Consumer>
...
Run Code Online (Sandbox Code Playgroud)
Str*_*ped 11
阅读React-Context的源代码,就可以了
<MyContext.Provider value={{
state: this.state,
}}>
Run Code Online (Sandbox Code Playgroud)
和
<MyContext.Consumer>
{(context) => <p>{context.state.age}</p>}
Run Code Online (Sandbox Code Playgroud)
所以,如果你这样做
<MyContext.Provider value={{ somevalue: 1 }}>
{this.props.children}
</MyContext.Provider>
Run Code Online (Sandbox Code Playgroud)
你应该somevalue
那样
<MyContext.Consumer>
{(context) => <div>{context.somevalue}</div>}
</MyContext.Consumer>
Run Code Online (Sandbox Code Playgroud)
编辑
如果您创建一个名为的文件myContext.js
,该怎么办:
const MyContext = React.createContext('test');
export default MyContext;
Run Code Online (Sandbox Code Playgroud)
然后导入它像:
import MyContext form '<proper_path>/myContext';
截至目前,即使名称相同,您在文件中创建的两个上下文也不相同。您需要导出您在其中一个文件中创建的上下文,并始终使用它。
所以像这样,在你的 provider.js 文件中:
import React, { Component } from 'react';
const MyContext = React.createContext();
export const MyContext;
export default class MyProvider extends Component {
render() {
return (
<MyContext.Provider
value={{ somevalue: 1 }}>
{this.props.children}
</MyContext.Provider >
);
}
}
Run Code Online (Sandbox Code Playgroud)
然后在你的 consumer.js 文件中
import MyContext from 'provider.js';
import React, { Component } from 'react';
export default class MyConsumer extends Component {
render() {
return (
<MyContext.Consumer>
{(context) => (
<div>{context.somevalue}</div>
)}
</MyContext.Consumer>
);
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
8980 次 |
最近记录: |