├── .vscode └── settings.json ├── public ├── robots.txt ├── favicon.ico ├── logo192.png ├── logo512.png ├── manifest.json └── index.html ├── src ├── utils.js ├── Components │ ├── testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest.js │ ├── Name.js │ ├── NameConsumer.js │ └── App.js ├── index.js └── Context │ └── NameContext.js ├── .gitignore ├── package.json └── README.md /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true 3 | } -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pranesh239/React-Context/master/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pranesh239/React-Context/master/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pranesh239/React-Context/master/public/logo512.png -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * no-operation function util 3 | * @return undefined 4 | */ 5 | export const noop = () => {}; 6 | -------------------------------------------------------------------------------- /src/Components/testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest.js: -------------------------------------------------------------------------------- 1 | console.log("test") 2 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './Components/App'; 4 | 5 | ReactDOM.render(, document.querySelector('#root')); 6 | -------------------------------------------------------------------------------- /src/Context/NameContext.js: -------------------------------------------------------------------------------- 1 | import { createContext } from 'react'; 2 | import { noop } from '../utils'; 3 | 4 | /** 5 | * **defaultValue** only used when a component does not have a matching 6 | * Provider above it in the tree 7 | */ 8 | const defaultValue = { 9 | name: 'Initial name', 10 | updateName: noop 11 | }; 12 | 13 | export default createContext(defaultValue); 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /src/Components/Name.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import NameContext from '../Context/NameContext'; 3 | 4 | class Name extends Component { 5 | static contextType = NameContext; 6 | render() { 7 | return ( 8 | <> 9 | {this.context.name} 10 | 11 | 12 | ); 13 | } 14 | } 15 | 16 | export default Name; 17 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/Components/NameConsumer.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import NameContext from '../Context/NameContext'; 3 | 4 | class NameConsumer extends Component { 5 | state = {}; 6 | render() { 7 | return ( 8 | 9 | {({ name, updateName }) => { 10 | return ( 11 | <> 12 |

{name}

13 | 14 | 15 | ); 16 | }} 17 |
18 | ); 19 | } 20 | } 21 | 22 | export default NameConsumer; 23 | -------------------------------------------------------------------------------- /src/Components/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import NameContext from '../Context/NameContext'; 3 | 4 | import Name from './Name'; 5 | import NameConsumer from './NameConsumer'; 6 | 7 | class App extends Component { 8 | updateName = () => { 9 | this.setState(state => { 10 | return { 11 | name: 'Doe' 12 | }; 13 | }); 14 | }; 15 | 16 | state = { 17 | name: 'John', 18 | updateName: this.updateName 19 | }; 20 | 21 | render() { 22 | return ( 23 | 24 | 25 | 26 | 27 | ); 28 | } 29 | } 30 | 31 | export default App; 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "context-api", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "react": "^16.10.1", 7 | "react-dom": "^16.10.1", 8 | "react-scripts": "3.1.2" 9 | }, 10 | "scripts": { 11 | "start": "react-scripts start", 12 | "build": "react-scripts build", 13 | "test": "react-scripts test", 14 | "eject": "react-scripts eject" 15 | }, 16 | "eslintConfig": { 17 | "extends": "react-app" 18 | }, 19 | "browserslist": { 20 | "production": [ 21 | ">0.2%", 22 | "not dead", 23 | "not op_mini all" 24 | ], 25 | "development": [ 26 | "last 1 chrome version", 27 | "last 1 firefox version", 28 | "last 1 safari version" 29 | ] 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React's Context API 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React's Context API 2 | 3 | > Context provides a way to pass data through the component tree without having to pass props down manually at every level. 4 | 5 | 🚨 Use Context only when some data needs to be accessed by **many components at different nesting levels**. Apply it sparingly because it makes component reuse more difficult. 🚨 6 | 7 | ### Context creation 8 | 9 | src/Context/NameContext.js 10 | 11 | ```js 12 | import { createContext } from 'react'; 13 | import { noop } from '../utils'; 14 | 15 | /** 16 | * defaultValue only used when a component does not have a matching 17 | * Provider above it in the tree 18 | */ 19 | const defaultValue = { 20 | name: 'Initial name', 21 | updateName: noop 22 | }; 23 | 24 | const NamedContext = createContext(defaultValue); 25 | export default NamedContext; 26 | ``` 27 | 28 | ### Providing data through Context 29 | 30 | src/Components/App.js 31 | 32 | ```js 33 | import React, { Component } from 'react'; 34 | import NameContext from '../Context/NameContext'; 35 | 36 | import Name from './Name'; 37 | import NameConsumer from './NameConsumer'; 38 | 39 | class App extends Component { 40 | updateName = () => { 41 | this.setState(state => { 42 | return { 43 | name: 'Doe' 44 | }; 45 | }); 46 | }; 47 | 48 | state = { 49 | name: 'John', 50 | updateName: this.updateName 51 | }; 52 | 53 | render() { 54 | return ( 55 | // Context.Provider takes the responsibility in passing data to its nested components and those data are passed through its value prop 56 | 57 | 58 | 59 | 60 | ); 61 | } 62 | } 63 | 64 | export default App; 65 | ``` 66 | 67 | ### Consuming data from Context 68 | 69 | Consumption of data can be done in two ways: 70 | 71 | 1. through `static contextType` property _(Class.contextType)_ 72 | 2. through Context's `Consumer` component _(Context.Consumer)_ 73 | 74 | #### through Class.contextType 75 | 76 | _You can only subscribe to a single context using this API_ 77 | 78 | src/Components/Name.js 79 | 80 | ```js 81 | import React, { Component } from 'react'; 82 | import NameContext from '../Context/NameContext'; 83 | 84 | class Name extends Component { 85 | // contextType passes the data from provider through context (this.context) property of consuming class. 86 | static contextType = NameContext; 87 | 88 | render() { 89 | return ( 90 | <> 91 | {this.context.name} 92 | 93 | 94 | ); 95 | } 96 | } 97 | 98 | export default Name; 99 | ``` 100 | 101 | #### through Context.Consumer 102 | 103 | src/Components/NameConsumer.js 104 | 105 | `Context.Consumer` makes use of [render props component pattern](https://github.com/pranesh239/react-component-patterns/tree/render-props) to provide data 106 | 107 | ```js 108 | import React, { Component } from 'react'; 109 | import NameContext from '../Context/NameContext'; 110 | 111 | class NameConsumer extends Component { 112 | state = {}; 113 | render() { 114 | return ( 115 | 116 | {({ name, updateName }) => { 117 | return ( 118 | <> 119 |

{name}

120 | 121 | 122 | ); 123 | }} 124 |
125 | ); 126 | } 127 | } 128 | 129 | export default NameConsumer; 130 | ``` 131 | --------------------------------------------------------------------------------