|
| 1 | +## Intro |
| 2 | + |
| 3 | +Como vemos en el ejemplo _17 Context_ esto es una poderosa característica. |
| 4 | + |
| 5 | +Obtener datos de un _Context.Consumer_ necesita un poco de tubería, hasta ahora hemos utilizado HOC (ejemplo 18) y Render Props (ejemplo 19) para incluir eso en un código reutilizable, eso estuvo bien, pero necesitabas agregar un margen de beneficio adicional a nuestros componentes, hacer un uso intensivo de HOC y RenderProps puede llevarlo a _markup hell_ (muchos accesorios de HOC / Render props). |
| 6 | + |
| 7 | +Veamos como se resuelve esto utilizando Hooks + Use Context. |
| 8 | + |
| 9 | +## Prerequisitos |
| 10 | + |
| 11 | +Instalar [Node.js y npm](https://nodejs.org/en/) (v6.6.0 o superior) si no las tenemos instaladas en nuestro ordenador. |
| 12 | + |
| 13 | +> Verifica que estás usando al menos node v6.x.x y npm 3.x.x usando los comandos `node -v` y `npm -v` en una terminal o consola. Las versiones anteriores pueden producir errores. |
| 14 | +
|
| 15 | +## Pasos para construirlo |
| 16 | + |
| 17 | +- Vamos a copiar el código del ejemplo _21 Hooks_. |
| 18 | + |
| 19 | +- Vamos a instalar las dependencias. |
| 20 | + |
| 21 | +```bash |
| 22 | +npm install |
| 23 | +``` |
| 24 | + |
| 25 | +- Ahora vamos a desistalar la versión actual de react y react-dom: |
| 26 | + |
| 27 | +```bash |
| 28 | +npm uninstall react react-dom --save |
| 29 | +``` |
| 30 | + |
| 31 | +- E instalamos la versión alfa 16.7: |
| 32 | + |
| 33 | +```bash |
| 34 | + |
| 35 | +``` |
| 36 | + |
| 37 | +- Vamos a reemplazar la solución de render props con un _UseContext_ |
| 38 | + |
| 39 | +_./src/pages/pageB.tsx_ |
| 40 | + |
| 41 | +```diff |
| 42 | +- import * as React from "react" |
| 43 | ++ import * as React, {useContext} from "react" |
| 44 | +import { Link } from 'react-router-dom'; |
| 45 | +- import { Session } from '../../common/'; |
| 46 | ++ import { SessionContext } from '../../common'; |
| 47 | + |
| 48 | +// ... |
| 49 | + |
| 50 | +- export const PageB = () => |
| 51 | ++ export const PageB = () => { |
| 52 | ++ const loginContext = React.useContext(SessionContext) |
| 53 | ++ |
| 54 | ++ return ( |
| 55 | + |
| 56 | + <div> |
| 57 | +- <Session |
| 58 | +- render={ |
| 59 | +- login => ( |
| 60 | +- <LoginComponent login={login}></LoginComponent> |
| 61 | +- )} |
| 62 | +- > |
| 63 | ++ <LoginComponent login={loginContext.login}></LoginComponent> |
| 64 | + </div> |
| 65 | ++} |
| 66 | +``` |
| 67 | + |
| 68 | +- Asi que ahora nuestro componente _PageB_ se muestra tan simple como: |
| 69 | + |
| 70 | +_./src/pages/pageB.tsx_ |
| 71 | + |
| 72 | +```tsx |
| 73 | +export const PageB = () => { |
| 74 | + const loginContext = React.useContext(SessionContext); |
| 75 | + |
| 76 | + return ( |
| 77 | + <div> |
| 78 | + <LoginComponent login={loginContext.login}></LoginComponent> |
| 79 | + </div> |
| 80 | + ) |
| 81 | +} |
| 82 | +``` |
| 83 | + |
| 84 | +- Ahora podemos eliminar el helper de _renderProps_ que creamos. |
| 85 | + |
| 86 | +_./src/common/sessionContext.tsx_ |
| 87 | + |
| 88 | +```diff |
| 89 | +import * as React from "react" |
| 90 | + |
| 91 | +export interface SessionContextProps { |
| 92 | + login: string; |
| 93 | + updateLogin: (value) => void; |
| 94 | +} |
| 95 | + |
| 96 | +export const createDefaultUser = (): SessionContextProps => ({ |
| 97 | + login: 'no user', |
| 98 | + updateLogin: (value) => { }, |
| 99 | +}); |
| 100 | + |
| 101 | +export const SessionContext = React.createContext<SessionContextProps>(createDefaultUser()); |
| 102 | + |
| 103 | +interface State extends SessionContextProps { |
| 104 | +} |
| 105 | + |
| 106 | +export class SessionProvider extends React.Component<{}, State> { |
| 107 | + |
| 108 | + constructor(props) { |
| 109 | + super(props); |
| 110 | + this.state = { |
| 111 | + login: createDefaultUser().login, |
| 112 | + updateLogin: this.setLoginInfo |
| 113 | + } |
| 114 | + } |
| 115 | + |
| 116 | + setLoginInfo = (newLogin) => { |
| 117 | + this.setState({ login: newLogin }) |
| 118 | + } |
| 119 | + |
| 120 | + render() { |
| 121 | + return ( |
| 122 | + <SessionContext.Provider value={this.state}> |
| 123 | + {this.props.children} |
| 124 | + </SessionContext.Provider> |
| 125 | + ) |
| 126 | + }; |
| 127 | +}; |
| 128 | + |
| 129 | +interface Props { |
| 130 | + render : (login : string) => React.ReactNode; |
| 131 | +} |
| 132 | + |
| 133 | +- export class Session extends React.Component<Props> { |
| 134 | +- constructor(props : Props) { |
| 135 | +- super(props); |
| 136 | +- } |
| 137 | +- |
| 138 | +- render() { |
| 139 | +- return ( |
| 140 | +- <SessionContext.Consumer> |
| 141 | +- { |
| 142 | +- ({ login, updateLogin }) => |
| 143 | +- <> |
| 144 | +- {this.props.render(login)} |
| 145 | +- </> |
| 146 | +- } |
| 147 | +- </SessionContext.Consumer> |
| 148 | +- ) |
| 149 | +- } |
| 150 | +- } |
| 151 | +``` |
0 commit comments