@ -234,6 +234,61 @@ If your linter is [configured for React](/learn/editor-setup#linting), it will e
</Note>
<DeepDivetitle="Should all functions called during rendering start with the use prefix?">
No. Functions that don't *call* Hooks don't need to *be* Hooks.
If your function doesn't call any Hooks, avoid the `use` prefix. Instead, write it as a regular function *without* the `use` prefix. For example, `useSorted` below doesn't call Hooks, so call it `getSorted` instead:
```js
// 🔴 Avoid: A Hook that doesn't use Hooks
function useSorted(items) {
return items.slice().sort();
}
// ✅ Good: A regular function that doesn't use Hooks
function getSorted(items) {
return items.slice().sort();
}
```
This ensures that your code can call this regular function anywhere, including conditions:
```js
function List({ items, shouldSort }) {
let displayedItems = items;
if (shouldSort) {
// ✅ It's ok to call getSorted() conditionally because it's not a Hook
displayedItems = getSorted(items);
}
// ...
}
```
You should give `use` prefix to a function (and thus make it a Hook) if it uses at least one Hook inside of it:
```js
// ✅ Good: A Hook that uses other Hooks
function useAuth() {
return useContext(Auth);
}
```
Technically, this isn't enforced by React. In principle, you could make a Hook that doesn't call other Hooks. This is often confusing and limiting so it's best to avoid that pattern. However, there may be rare cases where it is helpful. For example, maybe your function doesn't use any Hooks right now, but you plan to add some Hook calls to it in the future. Then it makes sense to name it with the `use` prefix:
```js {3-4}
// ✅ Good: A Hook that will likely some other Hooks later
function useAuth() {
// TODO: Replace with this line when authentication is implemented:
// return useContext(Auth);
return TEST_USER;
}
```
Then components won't be able to call it conditionally. This will become important when you actually add Hook calls inside. If you don't plan to use Hooks inside it (now or later), don't make it a Hook.
</DeepDive>
### Custom Hooks let you share stateful logic, not state itself {/*custom-hooks-let-you-share-stateful-logic-not-state-itself*/}
In the earlier example, when you turned the network on and off, both components updated together. However, it's wrong to think that a single `isOnline` state variable is shared between them. Look at this code:
@ -1393,6 +1448,446 @@ If you use custom Hooks like `useData` above in your app, it will require fewer
</DeepDive>
### There is more than one way to do it {/*there-is-more-than-one-way-to-do-it*/}
Let's say you want to implement a fade-in animation *from scratch* using the browser [`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) API. You might start with an Effect that sets up an animation loop. During each frame of the animation, you could change the opacity of the DOM node you [hold in a ref](/learn/manipulating-the-dom-with-refs) until it reaches `1`. Your code might start like this:
<Sandpack>
```js
import { useState, useEffect, useRef } from 'react';
You could keep the `useFadeIn` code as is, but you could also refactor it more. For example, you could extract the logic for setting up the animation loop out of `useFadeIn` into a new custom Hook called `useAnimationLoop`:
<Sandpack>
```js
import { useState, useEffect, useRef } from 'react';
There's no one best way to do it. As with regular functions, ultimately you decide where to draw the boundaries between different parts of your code. Keep in mind that no abstraction at all is better than a wrong abstraction.
For example, you could also take a very different approach, and move the imperative logic into a JavaScript [class:](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)
<Sandpack>
```js
import { useState, useEffect, useRef } from 'react';
import { useFadeIn } from './useFadeIn.js';
function Welcome() {
const ref = useRef(null);
useFadeIn(ref, 1000);
return (
<h1className="welcome"ref={ref}>
Welcome
</h1>
);
}
export default function App() {
const [show, setShow] = useState(false);
return (
<>
<buttononClick={()=> setShow(!show)}>
{show ? 'Remove' : 'Show'}
</button>
<hr/>
{show &&<Welcome/>}
</>
);
}
```
```js useFadeIn.js active
import { useState, useEffect } from 'react';
import { FadeInAnimation } from './animation.js';
export function useFadeIn(ref, duration) {
useEffect(() => {
const animation = new FadeInAnimation(ref.current);
Effects let you connect React to external systems. The more coordination between Effects is needed (for example, to combine many animations), the more it makes sense to extract that logic out of Effects and Hooks *completely* like in the sandbox above. Then, the code you extracted *becomes* the "external system." This lets your Effects stay simple because they only need to send messages to the system you've moved outside React.
The examples above assume that the fade-in logic needs to be written in JavaScript. However, this particular fade-in animation is both simpler and much more efficient to implement with a plain [CSS Animation:](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations)
<Sandpack>
```js
import { useState, useEffect, useRef } from 'react';