From e817499383b5c9065bbf1c3b1cce6e96c6140194 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 14 Jun 2022 01:16:16 +0100 Subject: [PATCH] [Beta] Synchronizing with Effects (#4742) * [WIP] Effects * More * More * Typo * More * tweaks * typo * note * Add playsinline * Fix * Typo * Oops * More content * Compress a bit * edits * oops * Tweaks * tweak * Inline the deep dive * fix * typos * add deep dive * oops * Clarify * Add third case * oops * edit * [beta][effects] Reword effects-in-render counterexample (#4722) * reframe * oops * ok * edits * fix * remove special styling * tweak * oops * tweak * challenges * tweaks Co-authored-by: Sophie Alpert --- .../pages/learn/synchronizing-with-effects.md | 1498 +++++++++++++++++ beta/src/sidebarLearn.json | 4 + 2 files changed, 1502 insertions(+) create mode 100644 beta/src/pages/learn/synchronizing-with-effects.md diff --git a/beta/src/pages/learn/synchronizing-with-effects.md b/beta/src/pages/learn/synchronizing-with-effects.md new file mode 100644 index 00000000..d338f21e --- /dev/null +++ b/beta/src/pages/learn/synchronizing-with-effects.md @@ -0,0 +1,1498 @@ +--- +title: 'Synchronizing with Effects' +--- + + + +Some components need to synchronize with external systems. For example, you might want to control a non-React component based on the React state, set up a server connection, or send an analytics log when a component appears on the screen. *Effects* let you run some code after rendering so that you can synchronize your component with some system outside of React. + + + + + +- What effects are +- How effects are different from events +- How to declare an effect in your component +- Why effects run twice in development mode +- How to optimize effects with dependencies + + + +## What are effects and how are they different from events? {/*what-are-effects-and-how-are-they-different-from-events*/} + +Before getting to effects, you need to be familiar with two types of logic inside React components: + +- **Rendering code** (introduced in [Describing the UI](/learn/describing-the-ui)) lives at the top level of your component. This is where you take the props and state, transform them, and return the JSX you want to see on the screen. [Rendering code must be pure.](/learn/keeping-components-pure) Like a math formula, it should only _calculate_ the result, but not do anything else. + +- **Event handlers** (introduced in [Adding Interactivity](/learn/adding-interactivity)) are nested functions inside your components that *do* things rather than just calculate them. An event handler might update an input field, submit an HTTP POST request to buy a product, or navigate the user to another screen. Event handlers contain ["side effects"](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) (they change the program's state) and are caused by a specific user action (for example, a button click or typing). + +Sometimes this isn't enough. Consider a `ChatRoom` component that must connect to the chat server whenever it's visible on the screen. Connecting to a server is not a pure calculation (it's a side effect) so it can't happen during rendering. However, there is no single particular event like a click that causes `ChatRoom` to be displayed. + +***Effects* let you specify side effects that are caused by rendering itself, rather than by a particular event.** Sending a message in the chat is an *event* because it is directly caused by the user clicking a specific button. However, setting up a server connection is an *effect* because it needs to happen regardless of which interaction caused the component to appear. Effects run at the end of the [rendering process](/learn/render-and-commit) after the screen updates. This is a good time to synchronize the React components with some external system (like network or a third-party library). + + + +Here and later in this text, "effects" refers to the React-specific definition above, i.e. side effects caused by rendering. When we want to refer to the broader programming concept, we'll say "side effects". + + + + +## You might not need an effect {/*you-might-not-need-an-effect*/} + +**Don't rush to add effects to your components.** Keep in mind that effects are typically used to "step out" of your React code and synchronize with some *external* system. This includes browser APIs, third-party widgets, network, and so on. If your effect only adjusts some state based on other state, [you might not need an effect.](/learn/you-might-not-need-an-effect) + +## How to write an effect {/*how-to-write-an-effect*/} + +To write an effect, follow these three steps: + +1. **Declare an effect.** By default, your effect will run after every render. +2. **Specify the effect dependencies.** Most effects should only re-run *when needed* rather than after every render. For example, a fade-in animation should only trigger when a component appears. Connecting and disconnecting to a chat room should only happen when the component appears and disappears, or when the chat room changes. You will learn how to control this by specifying *dependencies.* +3. **Add cleanup if needed.** Some effects need to specify how to stop, undo, or clean up whatever they were doing. For example, "connect" needs "disconnect," "subscribe" needs "unsubscribe," and "fetch" needs either "cancel" or "ignore". You will learn how to do this by returning a *cleanup function*. + +Let's look at each of these steps in detail. + +### Step 1: Declare an effect {/*step-1-declare-an-effect*/} + +To declare an effect in your component, import the [`useEffect` Hook](/api/useeffect) from React: + +```js +import { useEffect } from 'react'; +``` + +Then, call it at the top level of your component and put some code inside your effect: + +```js {2-4} +function MyComponent() { + useEffect(() => { + // Code here will run after *every* render + }); + return
; +} +``` + +Every time your component renders, React will update the screen *and then* run the code inside `useEffect`. In other words, **`useEffect` "delays" a piece of code from running until that render is reflected on the screen.** + +Let's see how you can use an effect to synchronize with an external system. Consider a `` React component. It would be nice to control whether it's playing or paused by passing an `isPlaying` prop to it: + +```js +; +``` + +Your custom `VideoPlayer` component renders the built-in browser [`