As we saw in sample 17 Context this is a powerfull feature.
Getting data from a Context.Consumer needs some plumbing, we have used so far HOC (example 18) and Render Props (example 19) to wrap that into some reusable code, that was nice but it needed to add some extra markup to our components, making heavy use of HOC and RenderProps can lead you to the markup hell (lot of nested HOC / Render props).
Let's see how this is solved using Hooks + Use Context.
Install Node.js and npm (v6.6.0) if they are not already installed on your computer.
Verify that you are running at least node v6.x.x and npm 3.x.x by running
node -v
andnpm -v
in a terminal/console window. Older versions may produce errors.
-
Let's copy the code from sample 19 RenderProps.
-
Let's install the dependencies.
npm install
- Now we are going to uninstall current version of react and react-dom:
npm uninstall react react-dom --save
- And install the 16.7 alfa version:
npm install [email protected] [email protected] --save
- Let's replace the render props solution with a UseContext.
./src/pages/pageB.tsx
import * as React from "react"
import { Link } from 'react-router-dom';
- import { Session } from '../../common/';
+ import { SessionContext } from '../../common';
// ...
- export const PageB = () =>
+ export const PageB = () => {
+ const loginContext = React.useContext(SessionContext)
+
+ return (
<div>
- <Session
- render={
- login => (
- <LoginComponent login={login}></LoginComponent>
- )}
- >
+ <LoginComponent login={loginContext.login}></LoginComponent>
</div>
+}
- So now our PageB component looks as simple as:
./src/pages/pageB.tsx
export const PageB = () => {
const loginContext = React.useContext(SessionContext);
return (
<div>
<LoginComponent login={loginContext.login}></LoginComponent>
</div>
)
}
- Now we can get rid of the renderProps helper we created.
./src/common/sessionContext.tsx
import * as React from "react"
export interface SessionContextProps {
login: string;
updateLogin: (value) => void;
}
export const createDefaultUser = (): SessionContextProps => ({
login: 'no user',
updateLogin: (value) => { },
});
export const SessionContext = React.createContext<SessionContextProps>(createDefaultUser());
interface State extends SessionContextProps {
}
export class SessionProvider extends React.Component<{}, State> {
constructor(props) {
super(props);
this.state = {
login: createDefaultUser().login,
updateLogin: this.setLoginInfo
}
}
setLoginInfo = (newLogin) => {
this.setState({ login: newLogin })
}
render() {
return (
<SessionContext.Provider value={this.state}>
{this.props.children}
</SessionContext.Provider>
)
};
};
interface Props {
render : (login : string) => React.ReactNode;
}
- export class Session extends React.Component<Props> {
- constructor(props : Props) {
- super(props);
- }
-
- render() {
- return (
- <SessionContext.Consumer>
- {
- ({ login, updateLogin }) =>
- <>
- {this.props.render(login)}
- </>
- }
- </SessionContext.Consumer>
- )
- }
- }