152 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			152 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
|   | --- | |||
|  | title: Context API | |||
|  | --- | |||
|  | 
 | |||
|  | # Context API
 | |||
|  | 
 | |||
|  | The Context API has been implemented in the 16.3 version of React. | |||
|  | 
 | |||
|  | It existed before, but was in beta, and thus, unadvised to work with. | |||
|  | 
 | |||
|  | The goal of Context API is to allow developers to have an easy communication between components, without needing them to be closely related (Parent/Children components). | |||
|  | This also reduce the need for prop drilling (passing down the props through several components), which allows for a cleaner code, easier to maintain and update. | |||
|  | 
 | |||
|  | This get to its full potential when we want to share data that will be accessed by multiple components. | |||
|  | 
 | |||
|  | This is based around two things : a Provider and a Consumer. | |||
|  | 
 | |||
|  | ## Provider
 | |||
|  | 
 | |||
|  | On a file created exclusively to provide data, TimeProvider.js, let’s say we want to share some time between components. | |||
|  | 
 | |||
|  | ```javascript | |||
|  | // Import createContext | |||
|  | import React, { createContext, Component } from 'react'; | |||
|  | 
 | |||
|  | // Initialize a context with a time value to it | |||
|  | export const TimeContext = createContext({ | |||
|  |   time: '', | |||
|  | }); | |||
|  | 
 | |||
|  | // Create the TimeProvider class to be used by index.js as a provider and initialize a default value | |||
|  | class TimeProvider extends Component { | |||
|  |   state = { | |||
|  |     time: '17:00', | |||
|  |   }; | |||
|  | 
 | |||
|  |   // Passing the state that we just set as value to be used by our consumer and returning its children | |||
|  |   render() { | |||
|  |     return ( | |||
|  |       <TimeContext.Provider value={this.state}> | |||
|  |         {this.props.children} | |||
|  |       </TimeContext.Provider> | |||
|  |     ); | |||
|  |   } | |||
|  | } | |||
|  | 
 | |||
|  | export default TimeProvider; | |||
|  | ``` | |||
|  | We need to tweak a bit the component that will call the child which needs to consume our context (<ShowTime /> in this case). | |||
|  | 
 | |||
|  | ```javascript | |||
|  | // index.js | |||
|  | import React from "react"; | |||
|  | import ReactDOM from "react-dom"; | |||
|  | import { ShowTime} from "./ShowTime"; | |||
|  | 
 | |||
|  | // Importing our provider | |||
|  | import TimeProvider from "./utils/timeProvider"; | |||
|  | 
 | |||
|  | // Calling our Hello component inside our provider | |||
|  | function App() { | |||
|  |   return ( | |||
|  |       <TimeProvider> | |||
|  |         <ShowTime /> | |||
|  |       </TimeProvider> | |||
|  |   ); | |||
|  | } | |||
|  | 
 | |||
|  | const rootElement = document.getElementById("root"); | |||
|  | ReactDOM.render(<App />, rootElement); | |||
|  | ``` | |||
|  | 
 | |||
|  | ## Consumer
 | |||
|  | In the ShowTime.js file, let's call the time value using the consumer : | |||
|  | 
 | |||
|  | ```javascript | |||
|  | // on ShowTime.js | |||
|  | import React from “react”; | |||
|  | 
 | |||
|  | import { TimeContext } from “./utils/TimeProvider”; | |||
|  | 
 | |||
|  | export default () => ( | |||
|  |   <TimeContext.Consumer> | |||
|  |     {value => <p> It’s {value.time} ! </p>} | |||
|  |   </TimeContext.Consumer> | |||
|  | ); | |||
|  | ``` | |||
|  | 
 | |||
|  | This should show : | |||
|  | ```javascript | |||
|  | <p> It’s 17:00 ! </p> | |||
|  | ``` | |||
|  | 
 | |||
|  | ### Modify the context dynamically
 | |||
|  | In order to change the time that we’ll provide to the ShowTime component, we need to give our context a function, that can be used by the consumer to update a value. | |||
|  | 
 | |||
|  | Let’s just add it to our Provider | |||
|  | ```javascript | |||
|  | // utils.TimeProvider.js | |||
|  | ... | |||
|  | // This time we initialize a function to set the time | |||
|  | export const TimeContext = createContext({ | |||
|  |   time: "", | |||
|  |   setTime: () => {} | |||
|  | }); | |||
|  | 
 | |||
|  | // We define the setTime function to store the time we’ll give it | |||
|  | class TimeProvider extends Component { | |||
|  |   state = { | |||
|  |     time : "17:00", | |||
|  |     setTime: time => this.setState({ time : time }) | |||
|  |   }; | |||
|  | 
 | |||
|  |   render() { | |||
|  |     return ( | |||
|  |       <TimeContext.Provider value={this.state}> | |||
|  |         {this.props.children} | |||
|  |       </TimeContext.Provider> | |||
|  |     ); | |||
|  |   } | |||
|  | } | |||
|  | 
 | |||
|  | export default TimeProvider; | |||
|  | ``` | |||
|  | 
 | |||
|  | And back on our Consumer : | |||
|  | 
 | |||
|  | ```javascript | |||
|  | // on ShowTime.js | |||
|  | import React from “react”; | |||
|  | 
 | |||
|  | import { TimeContext } from “./utils/TimeProvider”; | |||
|  | 
 | |||
|  | export default () => ( | |||
|  |   <TimeContext.Consumer> | |||
|  |     {value => <p> It’s {value.time} ! </p>} | |||
|  |     <input type="text" value={time} onChange={e => setTime(e.target.value)} /> | |||
|  |   </TimeContext.Consumer> | |||
|  | ); | |||
|  | ``` | |||
|  | 
 | |||
|  | This will give us an input to modify the time that’ll be displayed. | |||
|  | 
 | |||
|  | We need to remember using three things : | |||
|  | - Create a Provider that will manage our data shared (also called a Store) | |||
|  | - Create a Consumer that will communicate with the store | |||
|  | - Surrounding our Consumer Component with the Provider created so it can use its data | |||
|  | 
 | |||
|  | ### More Information
 | |||
|  | 
 | |||
|  | - [React - Context Official Documentation ](https://reactjs.org/docs/context.html) |