I think the problem that you are running into is that you are creating two different contexts, and trying to use them as one. It is the Context
created by React.createContext
that links Provider
and Consumer
.
Make a single file (I'll call it 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;
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>
);
}
...
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
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;
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>
...
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…