Digging Into React Context

rfp-robotRFP ROBOT: Website Request for Proposal Generator

The time has come for a new website (or website redesign), which means you need to write a website request for proposal or web RFP. A Google search produces a few examples, but they vary wildly and don’t seem to speak really to your goals for developing or redesigning a new website. You need to write a website RFP that will clearly articulate your needs and generate responses from the best website designers and developers out there. But how?

Have no fear, RFP Robot is here. He will walk you through a step-by-step process to help you work through the details of your project and create a PDF formatted website design RFP that will provide the information vendors need to write an accurate bid. RFP Robot will tell you what info you should include, point out pitfalls, and give examples.


You may have wondered lately what all the buzz is about Context and what it might mean for you and your React sites. Before Context, when the management of state gets complicated beyond the functionality of setState, you likely had to make use of a third party library. Thanks to recent updates by the awesome React team, we now have Context which might help with some state management issues.

What Does Context Solve?
How do you move the state from a parent component to a child component that is nested in the component tree? You know that you can use Redux to manage state, but you shouldn’t have to jump to Redux in every situation.
There’s a way to do this without Redux or any other third party state management tool. You can use props!
Say the feature you want to implement has a tree structure similar to what I have below:

The state lives in the App component and is needed in UserProfile and UserDetails components. You need to pass it via props down the tree. If the components that need this state are 10 steps deep, this can become tedious, tiring, and error prone. Each component is supposed to be like a black box — other components should not be aware of states that they do not need. Here is an example of an application that matches the scenario above.
class App extends React.Component {
state = {
user: {
username: ‘jioke’,
firstName: ‘Kingsley’,
lastName: ‘Silas’
}
}

render() {
return(
<div>
<User user={this.state.user} />
</div>
)
}
}

const User = (props) => (
<div>
<UserProfile {…props.user} />
</div>
)

const UserProfile = (props) => (
<div>
<h2>Profile Page of {props.username}</h2>
<UserDetails {…props} />
</div>
)

const UserDetails = (props) => (
<div>
<p>Username: {props.username}</p>
<p>First Name: {props.firstName}</p>
<p>Last Name: {props.lastName}</p>
</div>
)

ReactDOM.render(<App />, document.getElementById(“root”));
We are passing the state from one component to another using props. The User component has no need of the state, but it has to receive it via props in order for it to get down the tree. This is exactly what we want to avoid.
See the Pen React Context API Pen 1 by Kingsley Silas Chijioke (@kinsomicrote) on CodePen.
Context to the Rescue!
React’s Context API allows you to store the state in what looks like an application global state and access it only in the components that need them, without having to drill it down via props.
We start by initializing a new Context using React’s createContext()
const UserContext = React.createContext({})
const UserProvider = UserContext.Provider
const UserConsumer = UserContext.Consumer
This new Context is assigned to a const variable, in this case, the variable is UserContext. You can see that there is no need to install a library now that createContext() is available in React (16.3.0 and above).
The Provider component makes the context available to components that need it, which are called Subscribers. In other words, the Provider component allows Consumers to subscribe to changes in context. Remember that the context is similar to a global application state. Thus, components that are not Consumers will not be subscribed to the context.
If you are coding locally, your context file will look like this:
import { createContext } from ‘react’

const UserContext = createContext({})
export const UserProvider = UserContext.Provider
export const UserConsumer = UserContext.Consumer
The Provider
We’ll make use of the Provider in our parent component, where we have our state.
class App extends React.Component {
state = {
user: {
username: ‘jioke’,
firstName: ‘Kingsley’,
lastName: ‘Silas’
}
}

render() {
return(
<div>
<UserProvider value={this.state.user}>
<User />
</UserProvider>
</div>
)
}
}
The Provider accepts a value prop to be passed to it Consumer components descendants. In this case, we will be passing the user state to the Consumer components. You can see that we are not passing the state to User component as props. That means we can edit the User component and exclude the props since it does not need them:
const User = () => (
<div>
<UserProfile />
</div>
)
The Consumer
Multiple components can subscribe to one Provider component. Our UserProfile component needs to make use of the context, so it will subscribe to it.
const UserProfile = (props) => (
<UserConsumer>
{context => {
return(
<div>
<h2>Profile Page of {context.username}</h2>
<UserDetails />
</div>
)
}}
</UserConsumer>
)
The data we injected into the Provider via the value prop is then made available in the context parameter of the function. We can now use this access the username of the user in our component.
The UserDetails component will look similar to the UserProfile component since it is subscriber to the same Provider:
const UserDetails = () => (
<div>
<UserConsumer>
{context => {
return (
<div>
<p>Userame: {context.username}</p>
<p>First Name: {context.firstName}</p>
<p>Last Name: {context.lastName}</p>
</div>
)
}}
</UserConsumer>
</div>
)
See the Pen React Context API Pen 2 by Kingsley Silas Chijioke (@kinsomicrote) on CodePen.
Updating State
What if we want to allow users to change their first and last name? That’s also possible. Consumer components can re-render whenever there are changes to the value passed by the Provider component. Let’s see an example.
We’ll have two input fields for the first and last name in the consumer component. From the Provider component, we will have two methods that update the state of the application using the values entered in the input fields. Enough talk, let’s code!
Our App component will look like this:
class App extends React.Component {
state = {
user: {
username: ‘jioke’,
firstName: ‘Kingsley’,
lastName: ‘Silas’
}
}

render() {
return(
<div>
<UserProvider value={
{
state: this.state.user,
actions: {
handleFirstNameChange: event => {
const value = event.target.value
this.setState(prevState => ({
user: {
…prevState.user,
firstName: value
}
}))
},

handleLastNameChange: event => {
const value = event.target.value
this.setState(prevState => ({
user: {
…prevState.user,
lastName: value
}
}))
}
}
}
}>
<User />
</UserProvider>
</div>
)
}
}
We are passing an object which contains state and actions to the value props which the Provider receives. The actions are methods that will be triggered when an onChange event happens. The value of the event is then used to update the state. Since we want to update either the first name or last name, there’s a need to preserve the value of the other. For this, we make use of ES6 Spread Operator, which allows us to update the value of the specified key.
With the new changes, we need to update UserProfile component.
const UserProfile = (props) => (
<UserConsumer>
{({state}) => {
return(
<div>
<h2>Profile Page of {state.username}</h2>
<UserDetails />
</div>
)
}}
</UserConsumer>
)
We use ES6 destructuring to extract state from the value received from the Provider.
For the UserDetails component, we both the state and actions. We also need to add two input fields that will listen for an onChange() event and call the corresponding methods.
const UserDetails = () => {
return (
<div>
<UserConsumer>
{({ state, actions }) => {
return (
<div>
<div>
<p>Userame: {state.username}</p>
<p>First Name: {state.firstName}</p>
<p>Last Name: {state.lastName}</p>
</div>
<div>
<div>
<input type=”text” value={state.firstName} onChange={actions.handleFirstNameChange} />
</div>
<div>
<input type=”text” value={state.lastName} onChange={actions.handleLastNameChange} />
</div>
</div>
</div>
)
}}
</UserConsumer>
</div>
)
}
Using Default Values
It is possible to pass default values while initializing Context. To do this, instead of passing an empty object to createContext(), we will pass some data.
const UserContext = React.createContext({
username: ‘johndoe’,
firstName: ‘John’,
lastName: ‘Doe’
})
To make use of this data in our application tree, we have to remove the provider from the tree. So our App component will look like this.
class App extends React.Component {
state = {
user: {
username: ‘jioke’,
firstName: ‘Kingsley’,
lastName: ‘Silas’
}
}

render() {
return(
<div>
<User />
</div>
)
}
}
See the Pen React Context API Pen 4 by Kingsley Silas Chijioke (@kinsomicrote) on CodePen.
The data that will be used in the Consumer components will be done defined when we initialized a new Context.
In Conclusion
When things get complicated, and you are tempted to run yarn install [<insert third-party library for state management], pause for a second — you’ve got React Context at the ready. Don’t you believe me? Maybe you’ll believe Kent C. Dodds.
The post Digging Into React Context appeared first on CSS-Tricks.
Source: CssTricks

Posted on June 11, 2018 in API, app, application, code, coding, css, drupal design,, Drupal Developer, drupal developer austin, Drupal Development, Drupal Support, Expert Drupal Development, global, The, user, Web Design Services

Share the Story

Back to Top