React use API vs useContext

Pro Members Only

This lesson is available if you have an active subscription.

Alternatively, some member might be able to gift it to you.

If you already have a subscription, you can sign in.

React use API vs useContext

Subscription Required

You must have an active subscription to access this content.
If you already have a subscription, you can sign in.

React use API

Modern react comes with a utility function called use that has a number of features. A core feature is that it can be used as a replacement for useContext and as we discuss below, use offers more flexibility.

Example with useContext

Here is a simple example where we call useContext to resolve the value of a context.

Button.tsx
ThemeContext.tsx
App.tsx
const baseStyle = {
borderRadius: "5px",
transition: "all .2s",
};
const lightStyle = {
...baseStyle,
background: "#fff",
color: "#000",
};
const darkStyle = {
...baseStyle,
background: "#000",
color: "#fff",
};

import { ThemeContext } from "./ThemeContext";
import { useContext } from "react";

export type ButtonProps = {
onClick: () => void;
children: React.ReactNode;
};

export const Button = (props: ButtonProps) => {
const theme = useContext(ThemeContext);
const style = theme == "light" ? lightStyle : darkStyle;

return (
<button style={style} onClick={props.onClick}>
{props.children}
</button>
);
};

Example with use

At its core use is a drop in replacement for useContext. So we can simply replace our call to useContext and get the same functionality. This is demonstrated below.

Button.tsx
ThemeContext.tsx
App.tsx
const baseStyle = {
borderRadius: "5px",
transition: "all .2s",
};
const lightStyle = {
...baseStyle,
background: "#fff",
color: "#000",
};
const darkStyle = {
...baseStyle,
background: "#000",
color: "#fff",
};

import { ThemeContext } from "./ThemeContext";
import { use } from "react";

export type ButtonProps = {
onClick: () => void;
children: React.ReactNode;
};

export const Button = (props: ButtonProps) => {
const theme = use(ThemeContext);
const style = theme == "light" ? lightStyle : darkStyle;

return (
<button style={style} onClick={props.onClick}>
{props.children}
</button>
);
};

Limitation of useContext

useContext must follow the rules of hooks and therefore it cannot be called conditionally or in loops.

As an example demonstrated below, even though we do not need the value from the context if custom styling is enabled, we still must make a called to useContext as we cannot call it conditionally.

Button.tsx
ThemeContext.tsx
App.tsx
const baseStyle = {
borderRadius: "5px",
transition: "all .2s",
};
const lightStyle = {
...baseStyle,
background: "#fff",
color: "#000",
};
const darkStyle = {
...baseStyle,
background: "#000",
color: "#fff",
};
const customStyle = {
...baseStyle,
background:
"linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet)",
color: "#fff",
};

import { ThemeContext } from "./ThemeContext";
import { useContext } from "react";

export type ButtonProps = {
onClick: () => void;
children: React.ReactNode;
isCustom?: boolean;
};

export const Button = (props: ButtonProps) => {
const { isCustom } = props;
const theme = useContext(ThemeContext);
const style = isCustom
? customStyle
: theme == "light"
? lightStyle
: darkStyle;

return (
<button style={style} onClick={props.onClick}>
{props.children}
</button>
);
};

Flexibility of use

The use API can be invoked conditionally and in loops.

As an example demonstrated below, we only read the value from the context if custom styling is disabled (isCustom is false).

Button.tsx
ThemeContext.tsx
App.tsx
const baseStyle = {
borderRadius: "5px",
transition: "all .2s",
};
const lightStyle = {
...baseStyle,
background: "#fff",
color: "#000",
};
const darkStyle = {
...baseStyle,
background: "#000",
color: "#fff",
};
const customStyle = {
...baseStyle,
background:
"linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet)",
color: "#fff",
};

import { ThemeContext } from "./ThemeContext";
import { use } from "react";

export type ButtonProps = {
onClick: () => void;
children: React.ReactNode;
isCustom?: boolean;
};

export const Button = (props: ButtonProps) => {
const { isCustom } = props;
const style = isCustom
? customStyle
: use(ThemeContext) == "light"
? lightStyle
: darkStyle;

return (
<button style={style} onClick={props.onClick}>
{props.children}
</button>
);
};

Limitation of use

use must be called from within the context of a React Component (either directly or from custom hooks).

As an example if you put this somewhere in the top level of your code you will get an error from React ESLint:

const value = use(ThemeContext);

The reason is that use still needs to resolve the passed context for some component. If you don't call use from a call stack that leads to a component, React cannot resolve the value for you.

This limitation is the same between use and useContext.

javascript
typescript
react
playwright

Enjoy free content straight from your inbox 💌

No spam, unsubscribe at any time.

Transcript

00:00

Modern React comes with utility function called use, which has a number of purposes. One of those purposes is that it can resolve a given context value similar to use context. So in this lesson we will look at how they are mostly similar and also discuss the key difference that makes use the better option going forward. To demonstrate, we have a simple application that has a theme context, which is a context whose value is either going to be resolved to the string light or dark. And then we wrap our application with a theme context provider. Within our application, we have two simple button components that are going to use the value that is going

00:32

to be provided by the context. Currently, they are going to get the value with the use context hook provided by React. This is the same application that we saw within our context lesson and you can see that it functions as expected as we change the value that is provided to the theme context provider. The value returned from use context reflects that change and we can use the light or the dark styles within the button. Now, as we mentioned at the start of this lesson, instead of using the use context hook, we can use the modern use API provided from React and it'll function the same

01:06

as use context and we can verify this change in the running application. As you can see, it still functions as expected. Let's talk about the difference between use and use context. Since use context is a hook, it must follow the rules of hooks, which means that we cannot call it conditionally to demonstrate that we have extended our application so that the buttons can either use the theme provided by the theme provider or they can use custom styles. If and is custom bullion is set to true, we maintain this bullion using you state wire it to a simple checkbox that allows the user

01:40

to either use the theme styles or custom styles and then pass in the value of this bullion to our individual button components. With this bullion passed in within our button components, we see the value that is passed in and store it in a variable called is custom. And if is custom is set to true. We use custom style, otherwise we look at the value provided by the context and depending upon its result, either use the lifestyle or the dark style. When we jump into our application, we can still use the styles provided by the theme or we can choose to override the styles.

02:12

And if we do so, the style will be independent of the theme and we will always use the custom style. This means that we should be able to make an optimization in our application and only invoke use context if we are going to need the value that it is returning. However, this is actually going to result in an error and this error will be called out by the ES l plugin provided by the React team. You can see that use context is underlined in red and the error is that the React hook use context is called conditionally.

02:43

According to the rules of hook, react hooks must be called in the exact same order in every component render, and therefore we cannot invoke it conditionally or within loops. Unlike use context, the use API in react breaks the convention of hoax in that it can be called conditionally. This is the reason why in modern react use is preferred overuse context, and this is actually highlighted within the React documentation as well. Use is preferred overuse context because it is more flexible. So if we take the same application and replace our usage of use context with use,

03:17

everything is going to work perfectly fine Use is going to behave the same as use context, except that it has the advantage that it can be called within conditions and loops. So with this error fixed, our application behaves the same as it did before with the added advantage that we only read the value of the context. If custom style is set to false, there is one restriction with the use function that is worth mentioning. It must be called from within the calling context of a React component. As an example, if we take our call to use and just move it to a top level module scope instead

03:51

of the context of a React component, it'll be caught by the React ES l plugin. The reason for this is that the context needs to be resolved for a particular component and when we call it from the top level, there isn't a related component for which React can resolve the context value. So all calls to use need to be from within the context of a React component, either directly from the React component or from within one of your custom hooks.