React 16.6 introduced the ability to consume data from context without using the Consumer component directly. This helps to cut down on unnecessary nesting in your components’ JSX, making them easier to read. In this lesson we’ll see how to replace a Consumer by using the contextType property.
Instructor: [00:00] React 16.6 introduced the ability for class components to access context directly without having to use a consumer and the render props pattern. To do this, at the top of the class, we can declare a static property called contextType and set it equal to the full user context.
[00:16] It needs to be the full context and not just the consumer. Right now, user context is only exporting provider and consumer. We'll go into that file. At the top, we'll create a variable called user context and save the context into there as well as destructuring provider and consumer.
[00:33] Then at the bottom, we can export this user context. Back in user menu, we can import the user context which we're already using. Down in the render function, we don't need to use the consumer anymore, because we can access these values directly.
[00:48] This.context is the value that was given to the provider, so we can destructure this directly into user and logout. Now, we can delete the consumer, and we've reduced the nesting by two levels and the app is still working.
[01:01] For a component that uses two contexts, like message list here with user consumer and email consumer, it's important to know that this contextType property is only available on classes.
[01:11] For a component like message list, we would have to convert this to a class before we could set the contextType and contextType only works for a single context. If it's using two contexts like this, we'd only be able to save one of them into contextType.
Hi Dave, How would you go about testing a class component that uses the static contextType field, instead of the render props method.
For instance:
class MyButton extends React.Component {
static contextType = UserContext
render() {
const { isConnected } = this.context
return(
<button>{isConnected() ? 'Disconnect' : 'Connect'}</button>
)
}
}
Currently trying to figure out if something like this would work
import { render } from 'react-testing-library'
import MyButton from '../mybutton'
test('it should change on connect', () => {
//Set Context like so?
MyButton.contextType = MockContext
const { container } = render(<MyButton/>)
})
That seems like it should work. Does it? If not, maybe you could mock the context at the module level: https://jestjs.io/docs/en/es6-class-mocks
FYI: The 'before' code for this lesson is here if you need it.