The code blog of Luke Karrys.

Safari Won't Play Videos via React useEffect

TL;DR View this example in Safari to see how playing a video via useEffect won’t work. If you’re attempting to make a video play inside a React effect, use useLayoutEffect .

useEffect vs useLayoutEffect

The React docs have the following tip that calls out when you should use useLayoutEffect vs useEffect :

Unlike componentDidMount or componentDidUpdate , effects scheduled with useEffect don’t block the browser from updating the screen. This makes your app feel more responsive. The majority of effects don’t need to happen synchronously. In the uncommon cases where they do (such as measuring the layout), there is a separate useLayoutEffect Hook with an API identical to useEffect .

In my experience, it’s pretty obvious when running an effect that should be a layout effect, such as the measuring example called out in the React docs. And the even though the behavior of useEffect is slightly different in timing from the previous componentDidMount and componentDidUpdate APIs, this advice makes a lot of sense and it is engrained in me now. When using hooks and writing effects, I always reach for useEffect first.

However, when developing livefromquarantine.club I found a case where it wasn’t obvious that I had to use useLayoutEffect instead of useEffect . I think my brain was holding on to ” useLayoutEffect is for measuring stuff!” and not realizing there are other events that need to be synchronous.

Safari WebKit Video Policies

Safari requires a user gesture to play video on both iOS and macOS . Here’s the specific policy from that link:

A <video> element can use the play() method to automatically play without user gestures only when it contains no audio tracks or has its muted property set to true .

I also found this WebKit blog post interesting for this section (emphasis mine):

A note about the user gesture requirement: when we say that an action must have happened “as a result of a user gesture”, we mean that the JavaScript which resulted in the call to video.play() , for example, must have directly resulted from a handler for a touchend , click , doubleclick , or keydown event. So, button.addEventListener('click', () => { video.play(); }) would satisfy the user gesture requirement. video.addEventListener('canplaythrough', () => { video.play(); }) would not.

So what if you try to call video.play() using React’s effects?

View this example on Codesandbox.

In other browsers like Chrome, both effects will work to play the video. But in Safari, only the useLayoutEffect will work. Even though play() is called via the onClick handler, Safari doesn’t see the play() call as the direct result of the click handler.

In order to get the video to play, you need to call play() from useLayoutEffect or directly in the onClick handler .

This also partially applies to the YouTube Player API. If you try to call ytPlayer.playVideo() inside useEffect a similar thing will happen. On iOS, the player will not start, but on macOS both the useEffect and useLayoutEffect handlers will behave the same.

Here's another example using the YouTube Player API.

In hindsight, this seems obvious but it wasn’t when I first ran into the issue in an application. It stumped me and wasn’t something I realized until walking around the house the next day.

A few lessons that I learned from this:

  • The example called out in the React docs is the most likely reason to use useLayoutEffect but it makes sense to learn what is happening under the hood so that cases like this are more immediately clear what’s happening. This probably applies to all APIs.
  • As always, reducing error cases as much as possible is very helpful. I first encountered the behavior when using the YouTube player but if I had reduced the case to using a plain <video> element I would’ve gotten this much nicer error from Safari: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission. Good error messages are very important.

Drop me a line if you have any questions, comments, or just want to say hi. Thanks for reading, you seem nice.

Filed Under

react video youtube safari hooks

Related Posts

React invariant violation / minified exception on ios 8 with webpack + babel march 14, 2016, posting to a photo blog on netlify with working copy and shortcuts april 10, 2021, announcing: live from quarantine club july 25, 2020.

HatchJS Logo

HatchJS.com

Cracking the Shell of Mystery

React useEffect not triggering: Causes and solutions

Avatar

**React useEffect Not Triggering: A Guide to Common Problems and Solutions**

React’s `useEffect` hook is a powerful tool for managing side effects in your components. However, it can sometimes be tricky to get working properly. In this guide, we’ll explore some of the most common problems that can occur with `useEffect`, and we’ll provide solutions for how to fix them.

We’ll start by discussing what `useEffect` is and how it works. Then, we’ll look at some of the common problems that can occur, such as `useEffect` not being triggered, `useEffect` being triggered too often, and `useEffect` being triggered with the wrong dependencies. Finally, we’ll provide solutions for how to fix each of these problems.

By the end of this guide, you’ll have a solid understanding of how `useEffect` works and how to use it to manage side effects in your React components.

What is `useEffect`?

`useEffect` is a React hook that allows you to perform side effects in your components. Side effects are any changes to the state of your application that are not directly related to the rendering of your components. For example, fetching data from a server, making a network request, or subscribing to a Redux store are all side effects.

`useEffect` takes two arguments: a callback function and an array of dependencies. The callback function is called whenever any of the dependencies change. This allows you to update your component’s state in response to changes in the outside world.

Here is a simple example of how to use `useEffect`:

js import React, { useEffect } from “react”;

const MyComponent = () => { const [todos, setTodos] = useState([]);

useEffect(() => { // Get todos from the server const todos = getTodosFromServer();

// Set the todos state setTodos(todos); }, []);

  • {todo.text}

export default MyComponent;

In this example, the `useEffect` hook is used to fetch todos from the server and update the `todos` state. The callback function is called whenever the dependencies array changes. In this case, the dependencies array is empty, so the callback function is called only once, when the component is first rendered.

Common Problems with `useEffect`

There are a few common problems that can occur with `useEffect`, such as:

`useEffect` not being triggered

`useEffect` being triggered too often

`useEffect` being triggered with the wrong dependencies

We’ll discuss each of these problems in more detail below.

One common problem with `useEffect` is that it might not be triggered when you expect it to be. This can happen for a variety of reasons, such as:

  • The dependencies array is empty.
  • The dependencies array contains a function that returns .
  • The dependencies array contains a function that throws an error.

To fix this problem, make sure that the dependencies array contains at least one value that is not empty or . You can also use the `useRef` hook to create a reference to a value that will never change, and use that value as a dependency.

Another common problem with `useEffect` is that it might be triggered too often. This can happen if the dependencies array changes too often, or if the callback function is doing too much work.

To fix this problem, you can try to reduce the number of dependencies in the dependencies array. You can also try to make the callback function more efficient.

Finally, it’s also possible for `useEffect` to be triggered with the wrong dependencies. This can happen if the dependencies array changes after the callback function has been called.

To fix this problem, you can use the `useRef` hook to create a reference to the dependencies array. Then, you can use the `useEffect` hook to listen for changes to the `useRef` value.

`useEffect` is a powerful tool for managing side effects in React components. However, it can sometimes be tricky to get working properly. By understanding the common problems that can occur with `useEffect`, and by knowing how to fix them, you can

1. Causes of React useEffect not triggering

The `useEffect` hook is a powerful tool for managing side effects in React. However, it can be tricky to use correctly, and there are a number of common mistakes that can cause it to not trigger.

In this article, we’ll take a look at some of the most common causes of `useEffect` not triggering, and we’ll provide some tips on how to avoid them.

1.1. Forgetting to call `useEffect` in the render function

The most common cause of `useEffect` not triggering is forgetting to call it in the render function. This is because `useEffect` is a **lifecycle hook**, which means that it is only called when the component is first rendered, or when its props or state change.

If you forget to call `useEffect` in the render function, then it will never be called, and your side effects will never be executed.

To avoid this problem, make sure to call `useEffect` in the render function of your component, like this:

js const MyComponent = ({ data }) => { // …

useEffect(() => { // This code will be executed when the component is first rendered, // or when its props or state change. }, [data]);

// … };

1.2. Using the wrong dependency array

The second most common cause of `useEffect` not triggering is using the wrong dependency array. The dependency array is a list of values that `useEffect` uses to determine whether it needs to be re-executed.

If you include a value in the dependency array that does not actually change, then `useEffect` will not be re-executed when that value changes. This can lead to your side effects not being executed when they should be.

To avoid this problem, make sure to only include values in the dependency array that actually change. For example, if you are using `useEffect` to listen for changes to the `data` prop, then you should include `data` in the dependency array. However, if you are using `useEffect` to listen for changes to the `id` prop, then you should not include `id` in the dependency array, because the `id` prop is not likely to change.

1.3. Using `useEffect` with a function component

The `useEffect` hook can only be used with **class components**. If you try to use `useEffect` with a function component, then it will not work.

To avoid this problem, make sure to use `useEffect` with a class component, like this:

js class MyComponent extends React.Component { // …

1.4. Using `useEffect` with a render prop

The `useEffect` hook can also be used with **render props**. However, there are a few things to keep in mind when using `useEffect` with a render prop.

First, you need to make sure that the render prop function is called in the render function of your component. This is because `useEffect` is a lifecycle hook, and it is only called when the component is first rendered, or when its props or state change.

Second, you need to make sure that the render prop function returns a function. This is because `useEffect` needs to be able to call the render prop function in order to update the component’s state.

Here is an example of how to use `useEffect` with a render prop:

js const MyComponent = ({ data }) => { const renderProp = () => { // This code will be executed when the component is first rendered, // or when its props or state change.

1.5. Using `useEffect` with a custom hook

The `useEffect` hook can also be used with custom hooks . However, there are a few things to keep in mind when using `useEffect` with a custom hook.

First, you need to make sure that the custom hook is called in the render function of your component. This is because `useEffect` is a lifecycle hook, and it is only called when the component is

3. Dependencies are not changing

One common reason why `useEffect` might not be triggering is because the dependencies passed to it are not changing. This can happen if the dependencies are immutable objects, or if they are being read from a cache.

To fix this, you can make sure that the dependencies are mutable objects, or that they are being read from a source that is always changing. For example, if you are using a Redux store, you can make sure that the dependencies are pulled from the store using `useSelector`.

Here is an example of how to use `useSelector` to fix a `useEffect` that is not triggering:

js import React, { useEffect, useState } from “react”; import { useSelector } from “react-redux”;

const App = () => { const [count, setCount] = useState(0);

const incrementCount = () => { setCount(count + 1); };

useEffect(() => { // This effect will only run when the count state changes // because we are using useSelector to get the count from the store // The effect will also run when the store is first loaded const count = useSelector(state => state.count); console.log(“Count:”, count); }, [count]);

Count: {count}

export default App;

In this example, the `useEffect` will only run when the `count` state changes. This is because we are using `useSelector` to get the `count` from the store. The effect will also run when the store is first loaded.

In this article, we discussed some of the reasons why `useEffect` might not be triggering. We covered common mistakes that people make when using `useEffect`, and we provided some tips for troubleshooting problems with `useEffect`.

If you are still having problems with `useEffect`, you can always ask for help on the React community forums.

Q: Why is my React useEffect hook not triggering?

A: There are a few possible reasons why your React useEffect hook might not be triggering. Here are some of the most common:

  • You are not using the hook correctly. The useEffect hook must be used in a functional component, and it must be called with a dependency array. For more information on how to use the useEffect hook, see the [React documentation](https://reactjs.org/docs/hooks-effect.html).
  • You are using the useEffect hook in a class component. The useEffect hook cannot be used in a class component. If you need to use a side effect in a class component, you can use the `componentDidMount` or `componentDidUpdate` lifecycle methods.
  • You are using the useEffect hook with a function that does not return a value. The useEffect hook must be called with a function that returns a value. This value will be used as the effect’s cleanup function. If your function does not return a value, the effect will not be cleaned up when the component unmounts.
  • You are using the useEffect hook with a function that throws an error. If your function throws an error, the useEffect hook will not be triggered. This is because React does not want to execute any side effects if there is a possibility that they could cause an error.

Q: How can I debug why my React useEffect hook is not triggering?

A: There are a few ways to debug why your React useEffect hook is not triggering. Here are some of the most common:

  • Use the React DevTools. The React DevTools can be used to inspect the state of your components and to debug any problems with your hooks. To open the React DevTools, open your browser’s developer tools and select the “React” tab.
  • Use the console. You can use the console to log the values of your variables and to inspect the output of your functions. This can help you to identify any problems with your code.
  • Use a debugger. You can use a debugger to step through your code and to see exactly what is happening at each step. This can help you to identify any problems with your code flow.

Q: How can I fix my React useEffect hook so that it triggers correctly?

A: There are a few things you can do to fix your React useEffect hook so that it triggers correctly. Here are some of the most common solutions:

  • Make sure you are using the hook correctly. The useEffect hook must be used in a functional component, and it must be called with a dependency array. For more information on how to use the useEffect hook, see the [React documentation](https://reactjs.org/docs/hooks-effect.html).
  • Make sure you are using the useEffect hook in a class component. The useEffect hook cannot be used in a class component. If you need to use a side effect in a class component, you can use the `componentDidMount` or `componentDidUpdate` lifecycle methods.
  • Make sure you are returning a value from your useEffect hook function. The useEffect hook must be called with a function that returns a value. This value will be used as the effect’s cleanup function. If your function does not return a value, the effect will not be cleaned up when the component unmounts.
  • Make sure your useEffect hook function does not throw an error. If your function throws an error, the useEffect hook will not be triggered. This is because React does not want to execute any side effects if there is a possibility that they could cause an error.

Q: What are some common mistakes people make when using the React useEffect hook?

A: There are a few common mistakes people make when using the React useEffect hook. Here are some of the most common:

  • Using the useEffect hook in a class component. The useEffect hook cannot be used in a class component. If you need to use a side effect in a class component, you can use the `componentDidMount` or `componentDidUpdate` lifecycle methods.
  • Not returning a value from the useEffect hook function. The useEffect hook must be called with a function that returns a value. This value will be used as the effect’s cleanup function. If your function does not return a value, the effect will not be cleaned up when the component unmounts.

* **Using the useEffect hook with

In this blog post, we discussed the common causes of the React useEffect hook not triggering and how to troubleshoot them. We covered the following topics:

  • The purpose of the useEffect hook
  • The different ways that the useEffect hook can be triggered
  • The most common causes of the useEffect hook not triggering
  • How to troubleshoot the useEffect hook not triggering

We hope that this blog post has been helpful in understanding the useEffect hook and how to troubleshoot it when it is not triggering. If you have any other questions, please feel free to leave them in the comments below.

Key takeaways:

  • The useEffect hook is used to perform side effects, such as fetching data from a server or subscribing to a Redux store.
  • The useEffect hook is triggered when a component is mounted, when a prop changes, or when a state variable changes.
  • The most common causes of the useEffect hook not triggering are:
  • Forgetting to call the useEffect hook in the component’s constructor
  • Using the wrong dependency array in the useEffect hook
  • Using the useEffect hook inside a function component that is rendered conditionally
  • To troubleshoot the useEffect hook not triggering, you can use the following steps:
  • Check the console for errors
  • Use the React DevTools to inspect the component’s state and props
  • Use the React Profiler to track the execution of the useEffect hook

Author Profile

Marcus Greenwood

Latest entries

  • December 26, 2023 Error Fixing User: Anonymous is not authorized to perform: execute-api:invoke on resource: How to fix this error
  • December 26, 2023 How To Guides Valid Intents Must Be Provided for the Client: Why It’s Important and How to Do It
  • December 26, 2023 Error Fixing How to Fix the The Root Filesystem Requires a Manual fsck Error
  • December 26, 2023 Troubleshooting How to Fix the `sed unterminated s` Command

Similar Posts

Can creepers see through glass.

Can Creepers See Through Glass? Creepers are one of the most iconic enemies in Minecraft, and their ability to climb walls and ceilings makes them a formidable foe. But can creepers see through glass? This is a question that has been debated by Minecraft players for years, and there is no definitive answer. Some players…

Can You Run 220 Volts on 12/2 Wire?(Explained)

Can You Run 220 on 12/2 Wire? You’re in the middle of a home improvement project, and you need to run a new 220-volt circuit. You look in your toolbox and see that you only have 12/2 wire. Can you use this wire for a 220-volt circuit? The answer is: it depends. In this article,…

What Size Wire Do I Need to Run a 100 Amp Subpanel?

What Size Wire Do I Need for a 100 Amp Subpanel? If you’re adding a new circuit to your home or upgrading an existing one, you may need to install a 100 amp subpanel. A subpanel is a smaller electrical panel that’s connected to your main electrical panel and distributes power to specific areas of…

No Bootable Medium Found: What to Do When Your PC Won’t Start

Have you ever been greeted with the dreaded “no bootable medium found” error message? If so, you know how frustrating it can be. This error can occur for a variety of reasons, but it usually means that your computer can’t find the operating system to boot from. In this article, we’ll take a look at…

Why Are Canadians in South Park? (Explained)

Why Are Canadians in South Park? South Park is a satirical animated comedy series that has been on the air for over 20 years. The show is known for its crude humor, irreverent political commentary, and over-the-top characters. One of the show’s most iconic characters is Randy Marsh, a dimwitted but well-meaning Colorado resident who…

Can You Use a 1-1/2 Pipe for a Shower Drain?

Can You Use 1 1/2 Pipe for Shower Drain? Your shower drain is an essential part of your bathroom, but what happens when it clogs? If you’re not sure how to fix it, you might be tempted to just replace the entire drain with a larger one. But is that really necessary? In this article,…

React Hooks – How to Use the useState & useEffect Hooks in Your Project

Okoro Emmanuel Nzube

Hooks allow function components to have access to state and other React features, such as lifecycle methods. These Hook features were introduced to React version 16.8.

One of the interesting things about the Hook features is that they let you use React without classes. This, in turn, helps simplify your codebase and helps you write cleaner and more intuitive code.

In this article, you will learn how to make use of the common Hooks in your project.

React Hooks Benefits

Let's go over some of the reasons why you might want to use Hooks in your project:

  • Easy to use and understand: With Hooks, you can write more straightforward code. These Hook commands can only be written inside a functional component.
  • Reusable code: Hooks allow you to reuse a particular logic used in one component across multiple other components.
  • Better optimization performance: Hooks offer a more efficient approach to utilizing React functionalities like state and lifecycle functions, resulting in improved performance as compared to class components in some situations.

Different Types of React Hooks

The React Hook features are of different types, ranging from the useState , useEffect , useRef , useReducer , and so on.

React Hook Rules

There are a few important rules when it comes to the React Hook features that should be strictly followed. Let's go over them in the following sections.

Hooks should be called inside a React function

Hooks should not be used inside a class component – they can and should only be called inside the React function.

This first rule essentially specifies that a Hook component should not be found in a class component, but in a functional component.

Here is the wrong way of implementing the Hook feature:

And here is the correct way of implementing the Hook feature:

The code example above shows a proper way of using a Hook feature.

If you use a Hook feature in a class component, just like in the first example, your code will raise an error. Therefore, you can only implement a Hook inside a function component.

Hooks can only be called at the top level of a component

You can only implement/call a React Hook at the top level of a component before any other code.

Using the code from the previous section as an example, you can see that immediately after function App () .

The next thing that comes is the Hook command –  in that example we used the useState Hook. That is what the second rule is all about.

Hooks cannot be used in a conditional statement

We have different types of conditional statements/rendering ranging from if , else , and so on.

The above rule means that conditionals cannot be applied directly to Hooks. This is the case because Hooks are called in the same order on every render of a functional component.

You can conditionally run Hooks within a functional component, but for this to work, this condition must be determined by top-level logic and should not be nested within any other blocks or components.

The reason for this is because Hooks need to be invoked at the highest level of the component, rather than under conditions, loops, or nested functions.

Here is an example:

From the example above, the useEffect hook is executed conditionally dependent on the value of the isMounted state variable.

Clicking the button causes the value of isMounted to alternate, either activating or deactivating the effect depending on the updated value.

This is deemed appropriate because the Hook is invoked at the highest level of the component and its condition is determined by the overarching logic within the component.

How to Use the useState Hook

The React useState Hook enables you to have state variables in functional components.

To make use of the state Hook, you must first import it into your project by using the import command.

The way useState works is that it gives us two variables. The first variable is known as the value of the state, and the second variable is a function used to update the state.

Here is an example of how to go about this:

From the code example above, you can see that the state Hook was used in a functional component and not a class component.

count and setCount are the two variables of the state Hook, where count is the current value of the state and setCount is used to update the value of the state. Therefore, whenever the button is clicked, setCount will update the value of the count.

How to Use the useEffect Hook

The useEffect hook in React is like a handy tool for functional components. It helps manage tasks that aren't directly related to showing stuff on the screen, like fetching data from the internet, retrieving data from API endpoints, or setting up timers. It can be used to update components even after they've been shown, making your app more dynamic.

Here's a basic example of how useEffect is used to fetch data from an API endpoint:

In the code example above, MyComponent is a functional component which utilizes React hooks, specifically useState and useEffect , to handle state management and execute side effects. The useState hook is used to initialize a state variable called data . This variable will store the data retrieved from an API endpoint.

The useEffect hook is used to request data from the API endpoint once the component initially renders. Within the useEffect , an asynchronous function fetchData is defined to fetch JSON data from the specified API endpoint using the fetch API.

If the data fetching is successful, the returned JSON data is saved in the data state variable using the setData function supplied by the useState hook.

The useEffect hook also optionally returns a cleaning function, which is currently empty but can be used for any necessary cleanup logic.

In the component's JSX, the fetched data is conditionally rendered. If the data is not null, a list <ul> is produced using items extracted from the data array using map.

Finally, the MyComponent function is exported as the default export from the module, allowing it to be imported and utilized in other sections.

As a developer, React Hooks are a very useful and powerful tool for functional components that make your work easy.

I believe that at this point you now know what a React Hook is and how to use the most popular ones.

Thanks for reading, and happy coding!

Hello, I go by the alias "Derek". I'm proficient in a wide range of technical skills, which I gained and continued to to hone through self-education.

If you read this far, thank the author to show them you care. Say Thanks

Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. Get started

Exploring React

Join me in the lab! A site for ReactJS Fun and Advice

useEffect hook not working right? Here are a couple of things you can check.

You can’t figure out why the UI is not updating as it should, and you’ve tried console.log and F12 and are still none the wiser. Wouldn’t it be nice if you could get past this and build and show off beautiful apps instead.

This list of common misunderstandings and how to over come them will probably (hopefully!) help fix your problem.

useEffect uses some advance JavaScript and programming concepts. But, despite being advanced, they are well within the reach of any React developer, with a little bit of time and practice. Let’s fix it!

Modifying State Directly

If you modify state directly (mutate it) then it can cause problems with re-rendering, but not always.

It can cause problems if you render any pure components in React. Pure components will assume that the props passed to them won’t be mutated. They make this assumption so that React can make object comparisons more quickly.

Although you can get away with it often, as a rule it is best not to modify state directly, and instead update the state to a brand new object.

There is a lot more on this subject in this blog post: Why Not To Modify React State Directly

Using an object or value from an older render

The code in a functional component gets called on every single render. This means a new “scope” is created, and all the variables exist in that scope.

When you use a variable from the component’s function in the useEffect callback, it will be the variable “for that scope”, or in other words “for that render”. If you are not careful you might be looking at data from an older render.

For example, if you create an object, such as an array for example inside your functional component, and then refer to this inside your useEffect callback, you will always be referring to the one that was created when the hook was created. The hook might cause things to happen later on, but you will still be referring to the same object.

This may or may not be what you want, but it’s important to understand what is happening here.

I have created an example below. It has an App component and a TimeComponent embedded inside it. Clicking the button update the time passed to the TimeComponent .

There is a useEffect in the TimeComponent that runs when the component firsts renders, because it passes an empty array for the dependencies argument. It sets up a timer to log the value of time every second.

However even though clicking the button updates the value of the time prop, the value logged from useEffect remains the same!

This is because it refers to the first time that created when the component was first rendered.

And this is all because of scopes – and it a React “thing”. It’s a feature of JavaScript itself. It can catch you out in function components and hooks, so it’s good to understand it.

Posted by Martin Capodici

Get your useEffect cheatsheet. FREE!

Subscribe now and I'll send you this cool little useEffect cheatsheet, that covers the features of useEffect so you spend less time hunting through the web.

I will also send weekly ReactJS tips and more cheatsheets that will save you time and reduce frustration and confusion. Enter your email below to get your cheetsheet now!

You have successfully joined our subscriber list.

.

Leave a Comment Cancel Reply

Your email address will not be published. Required fields are marked *

Save my name, email, and website in this browser for the next time I comment.

How the useEffect Hook Works (with Examples)

The useEffect Hook

The useEffect hook is the Swiss Army knife of all the hooks . It’s the solution to many problems: how to fetch data when a component mounts, how to run code when state changes or when a prop changes, how to set up timers or intervals, you name it.

Pretty much anything you want to “do” in a React component other than return JSX (any sort of side effect), will go into a useEffect. (and you can have more than one useEffect per component, too)

All this power comes with a tradeoff: useEffect can be confusing until you understand how it works.

In this post, we’re going to look at lots of useEffect examples so that you understand the mental model and can use it effectively in your own code.

Here’s what we’ll cover:

Prevent useEffect From Running Every Render

Useeffect does not actively “watch”, only run once, on mount, how to fix the warnings (don’t ignore the warnings), when does useeffect run, run useeffect on state change, run useeffect when a prop changes, focus on mount, fetch data with useeffect, re-fetch when data changes, useeffect vs lifecycle methods.

If you’ve used class components and lifecycle methods, read this section first.

If you’ve never touched classes and never intend to, you can disregard the comparison to lifecycles – but this section will still be useful for learning when useEffect runs and how it fits into React’s render cycle.

Let’s look at how to run code after a component mounts ( componentDidMount ), after it re-renders ( componentDidUpdate ), and before it unmounts ( componentWillUnmount ).

Try it out in CodeSandbox .

Click the Show/Hide button. Look at the console. It prints “unmounting” before it disappears, and “render!” when it reappears.

Now, try the Re-render button. With each click, it prints “unmounting” and “render!” every time.

Why is it “unmounting” with every render?

Well, the cleanup function you can (optionally) return from useEffect isn’t only called when the component is unmounted. It’s called every time before that effect runs – to clean up from the last run. This is actually more powerful than the componentWillUnmount lifecycle because it lets you run a side effect before and after every render, if you need to.

Not Quite Lifecycles

useEffect runs after every render (by default), and can optionally clean up for itself before it runs again.

Rather than thinking of useEffect as one function doing the job of 3 separate lifecycles, it might be more helpful to think of it simply as a way to run side effects after render – including the potential cleanup you’d want to do before each one, and before unmounting.

useEffect Cheatsheet preview

Before we go on, I have to ask...

If you want your effects to run less often, you can provide a second argument – an array of values. Think of them as the dependencies for that effect. If one of the dependencies has changed since the last time, the effect will run again. (It will also still run after the initial render)

Another way to think of this array: it should contain every variable that the effect function uses from the surrounding scope. So if it uses a prop? That goes in the array. If it uses a piece of state? That goes in the array.

Some frameworks are reactive , meaning they automatically detect changes and update the UI when changes occur.

React does not do this – it will only re-render in response to state changes.

useEffect, too, does not actively “watch” for changes. When you call useEffect in your component, this is effectively queuing or scheduling an effect to maybe run, after the render is done.

After rendering finishes, useEffect will check the list of dependency values against the values from the last render, and will call your effect function if any one of them has changed.

You can pass the special value of empty array [] as a way of saying “only run on mount, and clean up on unmount”. So if we changed our component above to call useEffect like this:

Then it will print “mounted” after the initial render, remain silent throughout its life, and print “unmounting…” on its way out.

Be careful with the second argument: It’s easy to forget to add an item to it if you add a dependency, and if you miss a dependency, then that value will be stale the next time useEffect runs and it might cause some strange problems.

A common mistake people make is to pass the [] to useEffect even though the effect does depend on some variables. If you’re using Create React App or the React ESLint rules, you’ll get a warning about this in the browser console. Don’t ignore these warnings!

You’re passing a function to useEffect. This function creates a closure , which “latches on” to the values of any variables it refers to, at the time the function is created.

The empty array says “never re-create the closure, because this effect doesn’t refer to any variables that will change”.

With the empty array being passed, useEffect will hang on to the first function you pass it, which in turn will hang on to references to all the (maybe stale) variables that were used inside it.

The entire point of the dependency array is to give you a way to tell React “Hey, one of my variables changed! Re-create that closure!”

If you get a warning, you need to fix it. Take all the variables it’s complaining about, and put them in the array. Usually that works fine.

Sometimes, you can get into an infinite loop, or a situation where the effect runs on every render even though it seems like it shouldn’t. In many cases, the easiest fix for this is to use the functional form of setState . I also cover a few situations where this can go wrong and how to fix them in Learn useEffect Over Lunch .

By default, useEffect runs after each render of the component where it’s called. This timing is easiest to see with an example. Look over the code below, and try the interactive example on CodeSandbox , making sure to open up the console so you can see the timing.

In this example, there are 3 nested components: Top contains Middle, and Middle contains Bottom. The timing of useEffect depends on when each component renders, and initially, all 3 will be rendered. You’ll see 3 messages printed to the console.

Notice, though, that React renders from the bottom up! In this case: Bottom, then Middle, then Top. It’s recursive – the parent is not “done” until all of its children have rendered, and the useEffect will only run after the render of a component is complete.

From then on, nothing will happen until you click on one of the elements to increment its count. When you do, the only components that will re-render are the one you clicked, and the ones below it. (Notice that if you click on Bottom , you won’t see “rendered” messages from Top or Middle)

By default, useEffect runs after every render, but it’s also perfect for running some code in response to a state change. You can limit when the effect runs by passing the second argument to useEffect.

Think of the second argument as an array of “dependencies” – variables that, if changed, the effect should rerun. These can be any kind of variable: props, state, or anything else.

In this example, there are 3 state variables, and 3 buttons. The effect will only run when count2 changes, and will stay quiet otherwise. Try the interactive example .

Just as we were able to set up useEffect to run when a state variable changed, the same can be done with props. Remember they’re all regular variables! useEffect can trigger on any of them.

In this example, the PropChangeWatch component is receiving 2 props ( a and b ), and its effect will only run when the value of a changes (because we’re passing an array containing [a] as the second argument).

Try out the interactive example .:

Sometimes you just want to do one tiny thing at mount time, and doing that one little thing requires rewriting a function as a class.

In this example, let’s look at how you can focus an input control upon first render, using useEffect combined with the useRef hook.

At the top, we’re creating an empty ref with useRef . Passing it to the input’s ref prop takes care of setting it up once the DOM is rendered. And, importantly, the value returned by useRef will be stable between renders – it won’t change.

So, even though we’re passing [inputRef] as the 2nd argument of useEffect , it will effectively only run once, on initial mount. This is basically “componentDidMount” (except the timing of it, which we’ll talk about later).

To prove it, try out the example . Notice how it focuses (it’s a little buggy with the CodeSandbox editor, but try clicking the refresh button in the “browser” on the right). Then try typing in the box. Each character triggers a re-render, but if you look at the console, you’ll see that “render” is only printed once.

Let’s look at another common use case: fetching data and displaying it. In a class component, you’d put this code in the componentDidMount method. To do it with hooks, we’ll pull in useEffect . We’ll also need useState to store the data.

It’s worth mentioning that when the data-fetching portion of React’s new Suspense feature is ready, that’ll be the preferred way to fetch data. Fetching from useEffect has one big gotcha (which we’ll go over) and the Suspense API is going to be much easier to use.

Here’s a component that fetches posts from Reddit and displays them:

You’ll notice that we aren’t passing the second argument to useEffect here. This is bad. Don’t do this.

Passing no 2nd argument causes the useEffect to run every render. Then, when it runs, it fetches the data and updates the state . Then, once the state is updated, the component re-renders, which triggers the useEffect again. You can see the problem.

To fix this, we need to pass an array as the 2nd argument. What should be in the array?

Go ahead, think about it for a second.

The only variable that useEffect depends on is setPosts . Therefore we should pass the array [setPosts] here. Because setPosts is a setter returned by useState , it won’t be recreated every render, and so the effect will only run once.

Fun fact: When you call useState , the setter function it returns is only created once! It’ll be the exact same function instance every time the component renders, which is why it’s safe for an effect to depend on one. This fun fact is also true for the dispatch function returned by useReducer .

Let’s expand on the example to cover another common problem: how to re-fetch data when something changes, like a user ID, or in this case, the name of the subreddit.

First we’ll change the Reddit component to accept the subreddit as a prop, fetch the data based on that subreddit, and only re-run the effect when the prop changes:

This is still hard-coded, but now we can customize it by wrapping the Reddit component with one that lets us change the subreddit. Add this new App component, and render it at the bottom:

Try the working example on CodeSandbox .

The app is keeping 2 pieces of state here – the current input value, and the current subreddit. Submitting the input “commits” the subreddit, which will cause Reddit to re-fetch the data from the new selection. Wrapping the input in a form allows the user to press Enter to submit.

btw: Type carefully. There’s no error handling. If you type a subreddit that doesn’t exist, the app will blow up. Implementing error handling would be a great exercise though! ;)

We could’ve used just 1 piece of state here – to store the input, and send the same value down to Reddit – but then the Reddit component would be fetching data with every keypress.

The useState at the top might look a little odd, especially the second line:

We’re passing an initial value of “reactjs” to the first piece of state, and that makes sense. That value will never change.

But what about that second line? What if the initial state changes ? (and it will, when you type in the box)

Remember that useState is stateful ( read more about useState ). It only uses the initial state once , the first time it renders. After that it’s ignored. So it’s safe to pass a transient value, like a prop that might change or some other variable.

A Hundred And One Uses

The useEffect function is like the swiss army knife of hooks. It can be used for a ton of things, from setting up subscriptions to creating and cleaning up timers to changing the value of a ref.

One thing it’s not good for is making DOM changes that are visible to the user. The way the timing works, an effect function will only fire after the browser is done with layout and paint – too late, if you wanted to make a visual change.

For those cases, React provides the useMutationEffect and useLayoutEffect hooks, which work the same as useEffect aside from when they are fired. Have a look at the docs for useEffect and particularly the section on the timing of effects if you have a need to make visible DOM changes.

This might seem like an extra complication. Another thing to worry about. It kinda is, unfortunately. The positive side effect of this (heh) is that since useEffect runs after layout and paint, a slow effect won’t make the UI janky. The down side is that if you’re moving old code from lifecycles to hooks, you have to be a bit careful, since it means useEffect is almost-but-not-quite equivalent to componentDidUpdate in regards to timing.

Try Out useEffect

You can try useEffect on your own in this hooks-enabled CodeSandbox . A few ideas…

  • Render an input box and store its value with useState . Then set the document.title in an effect. (like Dan’s demo from React Conf )
  • Make a custom hook that fetches data from a URL
  • Add a click handler to the document, and print a message every time the user clicks. (don’t forget to clean up the handler!)

If you’re in need of inspiration, here is Nik Graf’s Collection of React Hooks – currently at 440 and counting! Most of them are simple to implement on your own. (like useOnMount , which I bet you could implement based on what you learned in this post!)

Learning React can be a struggle — so many libraries and tools! My advice? Ignore all of them :) For a step-by-step approach, check out my Pure React workshop .

Learn to think in React

  • 90+ screencast lessons
  • Full transcripts and closed captions
  • All the code from the lessons
  • Developer interviews

Dave Ceddia’s Pure React is a work of enormous clarity and depth. Hats off. I'm a React trainer in London and would thoroughly recommend this to all front end devs wanting to upskill or consolidate.

Alan Lavender

Want to get better at React?

Advisory boards aren’t only for executives. Join the LogRocket Content Advisory Board today →

LogRocket blog logo

  • Product Management
  • Solve User-Reported Issues
  • Find Issues Faster
  • Optimize Conversion and Adoption
  • Start Monitoring for Free

A complete guide to the useEffect React Hook

safari useeffect not working

Editor’s note : This article was last updated on 12 October 2023 to add a comparison of the useState and useEffect Hooks, the relationship between the useEffect Hook and React Server Components, and more.

A Complete Guide to the useEffect React Hook

Understanding how the useEffect Hook works is one of the most important concepts for mastering React today. Especially if you have been working with React for several years, it is crucial to understand how working with useEffect differs from working with the lifecycle methods of class-based components.

With useEffect , you invoke side effects from within functional components, which is an important concept to understand in the React Hooks era. Working with the side effects invoked by the useEffect Hook may seem cumbersome at first, but eventually, everything will make sense.

The goal of this article is to gather information about the underlying concepts of useEffect and to provide learnings from my own experience with the Hook. The code snippets provided are part of my companion GitHub project.

An introduction to useEffect

What are the effects, really? Examples include fetching data, reading from local storage, and registering and deregistering event listeners.

React’s effects are a completely different animal than the lifecycle methods of class-based components. The abstraction level differs, too. To their credit, lifecycle methods do give components a predictable structure. The code is more explicit in contrast to effects, so developers can directly spot the relevant parts (e.g., componentDidMount ) in terms of performing tasks at particular lifecycle phases (e.g., on component unmount).

As we will see later, the useEffect Hook fosters the separation of concerns and reduces code duplication. For example, the official React docs show that you can avoid the duplicated code that results from lifecycle methods with one useEffect statement.

A couple of key points to note before we get started:

  • Functions defined in the body of your function component get recreated on every render cycle. This has an impact if you use it inside of your effect. There are strategies to cope with it (for example, hoist them outside of the component, define them inside of the effect, use useCallback )
  • It is important to understand basic JavaScript concepts such as stale closures, otherwise, you might have trouble tackling problems with outdated props or state values inside of your effect
  • You should not ignore suggestions from the React Hooks ESLint plugin
  • Do not mimic the lifecycle methods of class-based components. This way of thinking does more harm than good. Instead, think more about data flow and state associated with effects because you run effects based on state changes across render cycles

Using useEffect for asynchronous tasks

For your fellow developers, useEffect code blocks are clear indicators of asynchronous tasks. Though it is possible to write asynchronous code without useEffect , it is not the “React way,” as it increases both complexity and the likelihood of introducing errors.

Instead of writing asynchronous code without useEffect , which might block the UI, using useEffect is a known pattern in the React community. With useEffect , developers can easily overview the code and quickly recognize code that is executed “outside the control flow,” which becomes relevant only after the first render cycle.

On top of that, useEffect blocks are candidates to extract into reusable and even more semantic custom Hooks.

When are effects executed within the component lifecycle?

This interactive diagram shows the React phases in which certain lifecycle methods (e.g., componentDidMount ) are executed:

A Diagram Of React's Most Common Lifecycle Methods

In contrast, the next diagram shows how things work in the context of functional components:

A Diagram Of The React Hooks Lifecycle

This may sound strange initially, but effects defined with useEffect are invoked after render. To be more specific, it runs both after the first render and after every update. In contrast to lifecycle methods, effects don’t block the UI because they run asynchronously.

If you are new to React, I would recommend ignoring class-based components and lifecycle methods and, instead, learning how to develop functional components and how to decipher the powerful possibilities of effects. Class-based components are rarely used in more recent React development projects .

If you are a seasoned React developer and are familiar with class-based components, you have to do some of the same things in your projects today as you did a few years ago when there were no Hooks.

For example, it is pretty common to “do something” when the component is first rendered. The difference with Hooks here is subtle: you do not do something after the component is mounted; you do something after the component is first presented to the user. Hooks force you to think more from the user’s perspective.

How does the useEffect Hook get executed?

This section briefly describes the control flow of effects. The following steps are carried out when executing an effect:

  • Initial render/mounting : When a functional component that contains a useEffect Hook is initially rendered, the code inside the useEffect block runs after the initial render of the component. This is similar to componentDidMount class components
  • Subsequent renders: You can pass a dependency array as the second argument to the useEffect Hook. This array contains variables or values that the effect depends on. Any change in these variables will re-render the component. If no dependency array is given, the effect will run on every render
  • Cleanup function : You can also run an optional cleanup function inside the effect. It is used to clean up any resources or subscriptions created by the effect when the component is unmounted or when the dependencies change
  • Unmounting : If a cleanup function is present, it is run and then the component is unmounted from the DOM

If one or more useEffect declarations exist for the component, React checks each useEffect to determine whether it fulfills the conditions to execute the implementation (the body of the callback function provided as the first argument). In this case, “conditions” mean one or more dependencies have changed since the last render cycle.

How to execute side effects with useEffect

The signature of the useEffect Hook looks like this:

Because the second argument is optional, the following execution is perfectly fine:

Let’s take a look at an example. The user can change the document title with an input field:

The useEffect statement is only defined with a single, mandatory argument to implement the actual effect to execute. In our case, we use the state variable representing the title and assign its value to document.title .

safari useeffect not working

Over 200k developers use LogRocket to create better digital experiences

safari useeffect not working

Because we skipped the second argument, this useEffect is called after every render. Because we implemented an uncontrolled input field with the help of the useRef Hook, handleClick is only invoked after the user clicks on the button. This causes a re-render because setTitle performs a state change.

After every render cycle, useEffect is executed again. To demonstrate this, I added two console.log statements:

The first two log outputs are due to the initial rendering after the component was mounted. Let’s add another state variable to the example to toggle a dark mode with the help of a checkbox:

However, this example leads to unnecessary effects when you toggle the darkMode state variable:

Of course, it’s not a big deal in this example, but you can imagine more problematic use cases that cause bugs or, at least, performance issues. Let’s take a look at the following code and try to read the initial title from local storage, if available, in an additional useEffect block:

As you can see, we have an infinite loop of effects because every state changes with setTitle triggers another effect, which updates the state again:

Dependency array items

The useEffect Hook’s second argument, known as the dependency array, serves the purpose of indicating the variables upon which the effect relies. This brings us to an important question: What items should be included in the dependency array?

According to the React docs , you must include all values from the component scope that change their values between re-renders. What does this mean, exactly?

All external values referenced inside of the useEffect callback function, such as props, state variables, or context variables, are dependencies of the effect. Ref containers (i.e., what you directly get from useRef() and not the current property) are also valid dependencies . Even local variables , which are derived from the aforementioned values, have to be listed in the dependency array.

The importance of the dependency array

Let’s go back to our previous example with two states (title and dark mode). Why do we have the problem of unnecessary effects?

Again, if you do not provide a dependency array, every scheduled useEffect is executed. This means that after every render cycle, every effect defined in the corresponding component is executed one after the other based on the positioning in the source code.

So the order of your effect definitions matters. In our case, our single useEffect statement is executed whenever one of the state variables changes. You have the ability to opt out of this behavior. This is managed with dependencies you provide as array entries. In these cases, React only executes the useEffect statement if at least one of the provided dependencies has changed since the previous run.

Let’s get back to our example where we want to skip unnecessary effects after an intended re-render. We just have to add an array with title as a dependency. With that, the effect is only executed when the values between render cycles differ:

Here’s the complete code snippet:

As you can see in the recording, effects are only invoked as expected when pressing the button:

It’s also possible to add an empty dependency array. In this case, effects are only executed once; it is similar to the componentDidMount() lifecycle method. To demonstrate this, let’s take a look at the previous example with the infinite loop of effects:

We just added an empty array as our second argument. Because of this, the effect is only executed once after the first render and skipped for the following render cycles:

In principle, the dependency array says, “Execute the effect provided by the first argument after the next render cycle whenever one of the arguments changes.” However, we don’t have any argument, so dependencies will never change in the future.

That’s why using an empty dependency array makes React invoke an effect only once — after the first render. The second render along with the second useEffect title is due to the state change invoked by setTitle() after we read the value from local storage.

Utilizing cleanup functions

The next snippet shows an example demonstrating a problematic issue:

This code implements a React component representing a counter that increases a number every second. The parent component renders the counter and allows you to destroy the counter by clicking on a button.

Take a look at the recording to see what happens when a user clicks on that button:

The child component has registered an interval that invokes a function every second. However, the component was destroyed without unregistering the interval. After the component is destroyed, the interval is still active and wants to update the component’s state variable ( count ), which no longer exists.

The solution is to unregister the interval right before unmounting. This is possible with a cleanup function. Therefore, you must return a callback function inside the effect’s callback body:

I want to emphasize that cleanup functions are not only invoked before destroying the React component. An effect’s cleanup function gets invoked every time right before the execution of the next scheduled effect.

Let’s take a closer look at our example. We used a trick to have an empty dependency array in the first place, so the cleanup function acts like a componentWillUnmount() lifecycle method. If we do not call setCount with a callback function that gets the previous value as an argument, we need to come up with the following code, wherein we add count to the dependencies array:

In comparison, the former example executes the cleanup function only once — on the mount — because we directly prevented using the state variable (count):

ESLint Warns About A Missing Prop

In this context, the latter approach is a small performance optimization because we reduce the number of cleanup function calls.

Comparing useState and useEffect

Both useState and useEffect improve functional components and allow them to do things that classes can and that functional components can’t do without Hooks. To understand the difference between the two better, we need to first understand the purpose of both these Hooks:

Purpose of useState

The useState Hook is used to manage state variables within a functional component, akin to how this.state works in class components. With useState , you can declare and initialize a state variable, and the Hook provides a function to update its value.

Purpose of useEffect

We have already delved into useEffect in detail. In essence, it empowers functional components with lifecycle methods similar to those found in class components. You can employ useEffect to perform actions such as data fetching, DOM manipulation, or the establishment of subscriptions in response to component lifecycle events.

While both of these hooks serve distinct purposes, they are frequently used in conjunction. For instance, states are often utilized in the dependency arrays of an effect, allowing components to re-render when state changes occur.

Implications of prop and state changes

There is a natural correlation between prop changes and the execution of effects because they cause re-renders, and as we already know, effects are scheduled after every render cycle.

Consider the following example. The plan is that the Counter component’s interval can be configured by a prop with the same name:

The handy ESLint plugin points out that we are missing something important: because we haven’t added the interval prop to the dependency array (having instead defined an empty array), the change to the input field in the parent component is without effect.

The initial value of 1000 is used even after we adjust the input field’s value:

The Initial Value Of 1000 Is Used Even After We Adjust The Input Field's Value

Instead, we have to add the prop to the dependency array:

Now things look much better:

useEffect inside of custom Hooks

Custom Hooks are awesome because they lead to various benefits:

  • Reusable code
  • Smaller components because of outsourced code (effects)
  • More semantic code due to the function calls of the custom Hooks inside of components
  • Effects can be tested when used inside of custom Hooks, as we’ll see in the next section

The following example represents a custom Hook for fetching data. We moved the useEffect code block into a function representing the custom Hook. Note that this is a rather simplified implementation that might not cover all your project’s requirements. You can find more production-ready custom fetch Hooks here :

The first statement within our React component, EffectsDemoCustomHook , uses the custom Hook useFetch . As you can see, using a custom Hook like this is more semantic than using an effect directly inside the component.

Business logic is nicely abstracted out of the component. We have to use our custom Hook’s nice API that returns the state variables loading and data .

The effect inside of the custom Hook is dependent on the scope variable url that is passed to the Hook as a prop. This is because we have to include it in the dependency array. So even though we don’t foresee the URL changing in this example, it’s still good practice to define it as a dependency. As mentioned above, there is a chance that the value will change at runtime in the future.

Additional thoughts on functions used inside of effects

If you take a closer look at the last example, we defined the fetchData function inside the effect because we only use it there. This is a best practice for such a use case. If we define it outside the effect, we need to develop unnecessarily complex code:

As you can see, we need to add fetchData to the dependency array of our effect. In addition, we need to wrap the actual function body of fetchData with useCallback with its own dependency ( url ) because the function gets recreated on every render.

By the way, if you move function definitions into effects, you produce more readable code because it is directly apparent which scope values the effect uses. The code is even more robust.

Furthermore, if you do not pass dependencies into the component as props or context, the ESLint plugin “sees” all relevant dependencies and can suggest forgotten values to be declared.

Using async functions inside of useEffect

If you recall our useEffect block inside the useFetch custom Hook, you might ask why we need this extra fetchData function definition. Can’t we refactor our code like so:

I’m glad you asked, but no! The following error will occur:

Async/await Produces A Runtime Error

The mighty ESLint plugin also warns you about it. The reason is that this code returns a promise, but an effect can only return void or a cleanup function.

Additional useEffect examples

In this section, I’ll show you some handy patterns that might be useful when using the useEffect Hook.

Execute an effect only once when a certain condition is met

As we already know, you control the execution of effects mainly with the dependency array. Every time one of the dependencies is changed, the effect is executed. You should design your components to execute effects whenever a state changes, not just once.

Sometimes, however, you want to trigger an effect only under specific conditions, such as when a certain event occurs. You can do this with flags that you use within an if statement inside of your effect.

The useRef Hook is a good choice if you don’t want to add an extra render (which would be problematic most of the time) when updating the flag. In addition, you don’t have to add the ref to the dependency array.

The following example calls the function trackInfo from our effect only if the following conditions are met:

  • The user clicked the button at least once
  • The user has ticked the checkbox to allow tracking

After the checkbox is ticked, the tracking function should only be executed after the user clicks on the button once again:

In this implementation, we utilized two refs: shouldTrackRef and infoTrackedRef . The latter is the “gate” to guarantee that the tracking function is only invoked once after the other conditions are met.

The effect is rerun every time count changes, i.e., whenever the user clicks on the button. Our if statement checks the conditions and executes the actual business logic only if it evaluates to true :

The log message user found the button component is only printed once after the right conditions are met.

Accessing data from previous renders

If you need to access some data from the previous render cycle, you can leverage a combination of useEffect and useRef :

We synchronize our effect with the state variable count so that it is executed after the user clicks on the button. Inside of our effect, we assign the current value of the state variable to the mutable current property of prevCountRef . We output both values in the JSX section:

When loading this demo, on initial render, the state variable has the initial value of the useState call. The ref value is undefined . It demonstrates once more that effects are run after render. When the user clicks, it works as expected.

When not to use useEffect

There are some situations in which you should avoid using useEffect due to potential performance concerns.

1. Transforming data for rendering

If you need to transform data before rendering, then you don’t need useEffect . Suppose you are showing a user list and only want to filter the user list based on some criteria. Maybe you only want to show the list of active users:

Here you can just do the filtering and show the users directly, like so:

This will save you time and improve the performance of your application.

2. Handling user events

You don’t need useEffect to handle user events. Let’s say you want to make a POST request once a user clicks on a form submit button. The following piece of code is inspired from React’s documentation :

In the above code, you can just make the post request once the button is clicked. But you are cascading the effect, so once the useEffect is triggered, it doesn’t have the complete context of what happened.

This might cause issues in the future; instead, you can just make the POST request on the handleSubmit function:

This is much cleaner and can help reduce future bugs.

React Server Components and UseEffect

React Server Components allow you to fetch and render components on the server, sending only the required data and parts of the UI to the client. The server pre-generates the initial HTML to prevent users from encountering a blank white page while the JavaScript bundles are being fetched and processed. Client-side React takes over from where server-side React left off, seamlessly integrating with the DOM and enhancing interactivity.

However, Server Components can’t re-render. And we can’t use effects or states because they only run after the render on the client, but Server Components are already rendered on the server.

Server Components are specifically crafted for server-side content pre-rendering, reducing their dependence on useEffect for data retrieval. Instead, they are capable of fetching data during the server rendering process and subsequently transmitting it as props to the client component.

So where can useEffect be used? Server components can pass data as props to the client components, which can then use useEffect to handle client-specific behavior. This approach can streamline the data flow and reduce the need for complex client-side data fetching logic.

Understanding the underlying design concepts and best practices of the useEffect Hook is a key skill to master if you wish to become a next-level React developer.

If you started your React journey before early 2019, you have to unlearn your instinct to think in lifecycle methods instead of thinking in effects.

Adopting the mental model of effects will familiarize you with the component lifecycle, data flow, other Hooks ( useState , useRef , useContext , useCallback , etc.), and even other optimizations like React.memo .

Get set up with LogRocket's modern React error tracking in minutes:

  • Visit https://logrocket.com/signup/ to get an app ID

Install LogRocket via npm or script tag. LogRocket.init() must be called client-side, not server-side

Share this:

  • Click to share on Twitter (Opens in new window)
  • Click to share on Reddit (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to share on Facebook (Opens in new window)

safari useeffect not working

Stop guessing about your digital experience with LogRocket

Recent posts:.

Signals Vs Ngonchanges For Better Angular State Management

Signals vs. ngOnChanges for better Angular state management

Angular is evolving in some exciting ways. Explore how signals enhance state management compared to the “old” approach using ngOnChanges .

safari useeffect not working

An advanced guide to Vitest testing and mocking

Use Vitest to write tests with practical examples and strategies, covering setting up workflows, mocking, and advanced testing techniques.

Optimizing Rendering In Vue

Optimizing rendering in Vue

This guide covers methods for enhancing rendering speed in Vue.js apps using functions and techniques like `v-once`, `v-for`, `v-if`, and `v-show`.

safari useeffect not working

Using Google Magika to build an AI-powered file type detector

Magika offers extremely accurate file type identification, using deep learning to address the limitations of traditional methods.

safari useeffect not working

22 Replies to "A complete guide to the useEffect React Hook"

Do you post on yb or twitter, so i can follow? Thanks.

Great article! Thank you! A small feedback in “The cleanup function is called multiple times.”, I think you put in the wrong video 😉

Updated. Thanks for pointing that out.

Great write up! One question I have is what are the benefits to using useEffect with the ‘gate’ ref and if checks for api calls that need to run only when a certain event happens like a button click? To me it seems harder to read and adding more complexity than just calling the api from the button click handler. I know that its ‘the react way’ but why is it better?

hi Julio, yes I’m on Twitter: https://twitter.com/doppelmutzi

Thanks Tdot. Regarding your question, using a “gate / boolean flag pattern” should only rarely be necessary. Most of the time, it points to problematic design. I also had to think long and hard to find an example for this article. In my everyday work, I almost never had to do something like this. This being said, in your described example you don’t need such a ref in combination with a button click. If I understand you right, you want to execute api calls whenever the user clicks a button – this falls into the normal pattern as I mentioned in the article “you should design your components to execute effects whenever a state changes, not just once”. If the user clicks your button, you update the state, a render happens, and then you can execute one or more effects depending on the changed state.

If I have misunderstood you, would you have a concrete example?

Regarding your statement that using this “gate pattern with refs” is more complicated – I am in complete agreement. Even with the small tracking example in this article, it is relatively complicated to execute a function only once when an event has occurred. You should avoid such an approach if possible (try to redesign your component) to have readable and understandable code.

} catch (error) { throw error; }

What is that??

This code is part of a simplified custom fetch hook and just re-throws the error again. In a real world project, you would most likey have a more advanced error handling, e.g., have another error state and return it to the callee to present some kind of error message / view.

Clearest and most comprehensive article on useEffect to date. Thank you!

Hello, I have a question about useEffect with functions in contexts. In your example you are using useCallback to avoid recreating the function but are creating a new object in the value of the provider. I have this confusion because of this https://reactjs.org/docs/context.html#caveats . So is it ok to do it like in your example or will it cause unintentional re-renders like in the example of the react docs? Thanks

Hello Alejandro, that’s a really good question! Yes, you’re right, there is a new object created with the following inline code value={{ onDarkModeChange }} which might lead to more re-renders of the IntervalComponent as necessary. So as you suggested with the react docu link, we could try to extract this object (maybe with useMemo?). I need to check this. However, my goal during the time of writing the article to make sure that the useEffect in the Counter component will not be invoked because of the re-creation of the onDarkModeChange function. Because we used useCallback in the EffectsDemoContext component and we do only use the same function reference all the time because of destructuring, the useEffect dependency is “stable”: const { onDarkModeChange } = useContext(EffectsContext);

I hope this was helpful for you!

it is a great article ,

Complete justice to the title!

This is a very good, and necessary article on useEffect, thank you for writing it.

I have to say, though, that the direction React is going scares me to death. One of the best things about React when I started using it 5 years ago is that it was easy to read and understand what was going on. This is patently false now. Take an experienced Javascript developer who has been using any other client-side tool for 5+ years, even non-hooks React, and show them the examples in this article. They will have absolutely no idea what is going on. How could they possibly understand what a function (useEffect) that takes a function and returns a function, with an optional data array does? The very fact that eslint has to have a god-level plugin to handle a dependency array should tell the developers that they have gone way, way off track.

The same example using objects might be complicated as well, but with well-named functions like componentDidMount it can be figured out without a deep dive into the docs and an article like this one. (This is a big deal when hiring new developers that have to go in and make minor changes to existing code.) Now take a code base of a couple hundred thousand lines, and you can see how much of a problem this becomes.

I understand the argument for hooks. I understand that it is better for solving some specific problems, and is great for small, uncomplicated projects. It is a nice *optional* addition. Yet having written some very complicated front ends, I can’t imagine creating a new project with React Hooks. I just hope the React devs never get rid of the object-based interface, or a mountain of rewriting is going to cripple a lot of companies for years.

Again, thanks for writing this, as we have no choice but to follow the React team’s lead, and the React docs are fairly trivial with their examples. This is much, much better. I have recently started writing all new code in Hooks, and am starting to hit all of the issues in this article (even for a relatively simple component).

Thank you very much John. I really appreciate your kind words.

In addition, I have the same thoughts like you. I have very good devs in my team but they do struggle sometimes with hooks and sometimes don’t even know because they don’t know some related concepts. You have to investigate and practice heavily to master hooks/React. We had for many weeks wrong usage of hooks because we had a wrong configuration regarding the eslint hook plugin. The consequences were we built the app around wrong/missing dependencies. After turning on the eslint plugin it was not easy to add the right deps and fix the app again. As you said the class based approach was more explicit and many devs had less problems.

I hope React gets easier again. There are some new frameworks that seems to be easier.

Hi! I forgot to mention here my thanks! This is a really great article, I follow up everything here with exercises and it really helps me a lot to understand and every day as a good practice for my React Project. I congratulate you for this great job! Thanks again!

Hey Patricio, that’s awesome. I’m glad the article helped you!

Do you have any guidelines for dependencies that use array values? they seem to suffer to similar side effects as functions do, since [1,2,3] === [1,2,3] is false.

Hi Shai, yes you’re right. The first thing I would do is to check if I can restructure my design to get rid of the array in the first place. If this is not possible, you most likely need useMemo. I made a quick research and found a “workaround” with JSON.stringify. Let’s take a look here, maybe this helps:

https://stackoverflow.com/a/59468261 https://github.com/facebook/react/issues/14476#issuecomment-471199055

Hi there is a mistake in the recording showing that exclduing count as dependency from useEffect will avoid cleanUp function from being called on every render. Your recording shows that ‘useEffect’ will be printed upon each execution of callback of setInterval, where as in reality it won’t. This is because you have excluded count variable from dependencies. So unless you have moved the console.log(“useEffect”) to your callback function passed to setInterval, the “useEffect” will be only printed once.

This article has cleared up all my useEffects misunderstandings. Thank you!

Nice block on useEffect Hook along with useState, useRef, useCallback with different scienarios.

Leave a Reply Cancel reply

If you’re familiar with React, then you’ve probably heard of the useEffect hook. It’s one of the most powerful and commonly used hooks in React, and it allows you to perform side effects in your components, such as fetching data from an API or setting up event listeners.

In Next.js, the useEffect hook is just as important, and it can be used in a variety of ways to enhance your application’s functionality and performance. If you’re using vanilla React, you might want to check out this article.

In this article, we’ll take a closer look at the useEffect hook in Next.js, exploring its syntax, use cases, and best practices. We’ll also provide some practical examples and code snippets to help you get started with using the useEffect hook in your Next.js applications.

So, whether you’re a seasoned React developer or new to the world of web development, read on to learn more about the useEffect hook in Next.js and how it can help you build better, more performant applications.

For the short version, the useEffect hook can be used to manage side-effects in your React components. It’s used to synchronise your component with some sort of external data source. Here’s what it looks like:

We have three components. Firstly the setup function; this gets called every time your useEffect gets triggered. Inside the setup function, you can return a cleanup function, which gets called every rerender. Then there’s the dependency array, which controls when your useEffect gets triggered.

Dependency Array

The dependency array is the second parameter of the useEffect hook. It controls when your useEffect gets re-ran. If you provide:

  • Nothing – The effect runs after every render
  • [ ] (Empty array) – The effect runs after the first render
  • [foo, bar] – The effect runs after the first render, and whenever foo or bar changes

Using these you can synchronise effects to run whenever you like.

Most commonly you’ll see useEffect functions with either an empty array, so the hook only runs once, or with variables in the dependency array, to keep a component synchronised.

Empty Array

With an empty array, your useEffect only runs on the first render. You might use this for example when fetching data that doesn’t depend on any parameters.

Here’s a pattern you might see often for data fetching:

We use our useEffect to start the data fetching when our component first renders. In our case the data doesn’t depend on any state or events, so we just need to fetch the data once our component has rendered.

With items in the dependency array, the hook runs on the first render, and whenever any of the values inside the dependency array changes.

If we take our previous example:

Imagine we have some component that displays user profiles, think something along the lines of Tinder swipe cards. In that case, the current user might be stored in state, in which case whenever we swipe, we need to fetch the new user.

No Dependencies

You might not see this option as much, just because it’s more common to have your useEffect hook synchronised with some external state, or to just run once. Additionally, it’s much easier to just place your logic inside the body of your component, which will run every render as well.

If we take our previous example again:

Here’s a possible example where you might want to have no dependencies in your useEffect array. In this case we have our imaginary social media, but now we’re taking in the user as a prop, and then fetching the friends list for our user in our component. Every time the user changes and our component re-renders, we re-fetch the list of users.

Note that in a real-world scenario, it’s important to ensure that the effect function is not doing something expensive or time-consuming. In this example, our imaginary effect function could be a small API request, or something more complex, in which case it may be necessary to include a dependency array just to ensure that it’s not executed unnecessarily.

Cleanup Functions

When using the useEffect hook in Next.js, it’s important to remember that it can potentially cause side effects and memory leaks if not used properly. That’s where the cleanup function comes in.

The cleanup function is a way to clean up any resources or effects created by the hook. It’s executed when the component is unmounted, before the new effect is applied (if there is one). This means that you can use it to cancel any ongoing network requests, unsubscribe from event listeners, or perform any other necessary cleanup.

To use the cleanup function, simply return a function from the effect callback. This function will be called when the component unmounts, allowing you to clean up any resources that were created during the effect.

Let’s take a look at a practical example:

Here’s a hook used to see if a screen matches a given media query. We can extract most of the logic, here’s the important parts:

We’re adding an event listener here to call our callback listener function whenever the screen gets resized. In a regular JavaScript program, you might not have to worry about removing the event listener. Your page gets loaded, the event listener gets added, and the event listener might exist for the whole time that the page is loaded.

In Next.js however, the component that uses this hook might get remounted or re-rendered several times. Every time that happens, that useEffect gets called, and our event listener gets added again. We need to return a cleanup function so that every time this does happen, the old one gets removed first.

To sum it up, the useEffect hook is an extremely useful hook used for synchronising your components with some effect, or external state, and using that to perform side effects in your component. It works by providing it a function to perform your side effect in, which can also return an optional clean up function to clean up any of your side effects, e.g. event listeners.

If you liked this article, or if you had any questions, feel free to leave a comment below!

Related Posts:

  • Brief Introduction To The useEffect Hook In React
  • Why is My useEffect Hook Running Twice in React?
  • Email Made Easy: A Step-by-Step Guide to Sending…
  • React Hooks Guide: How To Use Tutorial, Use Cases, Examples
  • Guide: Build a Real-Time Chat Application With ReactJS 🔥+⚛️
  • A Guide to Effective Error Handling in React

👋 Hey, I'm Omari Thompson-Edwards

💬 leave a comment cancel reply.

Your email address will not be published. Required fields are marked *

Upmostly brings you original JavaScript framework tutorials every week.

  • Cheatsheets
  • Write For Us

Copyright © 2024 Upmostly

useEffect is a React Hook that lets you synchronize a component with an external system.

useEffect(setup, dependencies?)

Connecting to an external system, wrapping effects in custom hooks, controlling a non-react widget, fetching data with effects, specifying reactive dependencies.

  • Updating state based on previous state from an Effect
  • Removing unnecessary object dependencies
  • Removing unnecessary function dependencies
  • Reading the latest props and state from an Effect

Displaying different content on the server and the client

My effect runs twice when the component mounts, my effect runs after every re-render, my effect keeps re-running in an infinite cycle, my cleanup logic runs even though my component didn’t unmount, my effect does something visual, and i see a flicker before it runs.

Call useEffect at the top level of your component to declare an Effect:

See more examples below.

setup : The function with your Effect’s logic. Your setup function may also optionally return a cleanup function. When your component is added to the DOM, React will run your setup function. After every re-render with changed dependencies, React will first run the cleanup function (if you provided it) with the old values, and then run your setup function with the new values. After your component is removed from the DOM, React will run your cleanup function.

optional dependencies : The list of all reactive values referenced inside of the setup code. Reactive values include props, state, and all the variables and functions declared directly inside your component body. If your linter is configured for React , it will verify that every reactive value is correctly specified as a dependency. The list of dependencies must have a constant number of items and be written inline like [dep1, dep2, dep3] . React will compare each dependency with its previous value using the Object.is comparison. If you omit this argument, your Effect will re-run after every re-render of the component. See the difference between passing an array of dependencies, an empty array, and no dependencies at all.

useEffect returns undefined .

useEffect is a Hook, so you can only call it at the top level of your component or your own Hooks. You can’t call it inside loops or conditions. If you need that, extract a new component and move the state into it.

If you’re not trying to synchronize with some external system, you probably don’t need an Effect.

When Strict Mode is on, React will run one extra development-only setup+cleanup cycle before the first real setup. This is a stress-test that ensures that your cleanup logic “mirrors” your setup logic and that it stops or undoes whatever the setup is doing. If this causes a problem, implement the cleanup function.

If some of your dependencies are objects or functions defined inside the component, there is a risk that they will cause the Effect to re-run more often than needed. To fix this, remove unnecessary object and function dependencies. You can also extract state updates and non-reactive logic outside of your Effect.

If your Effect wasn’t caused by an interaction (like a click), React will generally let the browser paint the updated screen first before running your Effect. If your Effect is doing something visual (for example, positioning a tooltip), and the delay is noticeable (for example, it flickers), replace useEffect with useLayoutEffect .

If your Effect is caused by an interaction (like a click), React may run your Effect before the browser paints the updated screen . This ensures that the result of the Effect can be observed by the event system. Usually, this works as expected. However, if you must defer the work until after paint, such as an alert() , you can use setTimeout . See reactwg/react-18/128 for more information.

Even if your Effect was caused by an interaction (like a click), React may allow the browser to repaint the screen before processing the state updates inside your Effect. Usually, this works as expected. However, if you must block the browser from repainting the screen, you need to replace useEffect with useLayoutEffect .

Effects only run on the client. They don’t run during server rendering.

Some components need to stay connected to the network, some browser API, or a third-party library, while they are displayed on the page. These systems aren’t controlled by React, so they are called external.

To connect your component to some external system, call useEffect at the top level of your component:

You need to pass two arguments to useEffect :

  • It should return a cleanup function with cleanup code that disconnects from that system.
  • A list of dependencies including every value from your component used inside of those functions.

React calls your setup and cleanup functions whenever it’s necessary, which may happen multiple times:

  • Your setup code runs when your component is added to the page (mounts) .
  • First, your cleanup code runs with the old props and state.
  • Then, your setup code runs with the new props and state.
  • Your cleanup code runs one final time after your component is removed from the page (unmounts).

Let’s illustrate this sequence for the example above.

When the ChatRoom component above gets added to the page, it will connect to the chat room with the initial serverUrl and roomId . If either serverUrl or roomId change as a result of a re-render (say, if the user picks a different chat room in a dropdown), your Effect will disconnect from the previous room, and connect to the next one. When the ChatRoom component is removed from the page, your Effect will disconnect one last time.

To help you find bugs, in development React runs setup and cleanup one extra time before the setup . This is a stress-test that verifies your Effect’s logic is implemented correctly. If this causes visible issues, your cleanup function is missing some logic. The cleanup function should stop or undo whatever the setup function was doing. The rule of thumb is that the user shouldn’t be able to distinguish between the setup being called once (as in production) and a setup → cleanup → setup sequence (as in development). See common solutions.

Try to write every Effect as an independent process and think about a single setup/cleanup cycle at a time. It shouldn’t matter whether your component is mounting, updating, or unmounting. When your cleanup logic correctly “mirrors” the setup logic, your Effect is resilient to running setup and cleanup as often as needed.

An Effect lets you keep your component synchronized with some external system (like a chat service). Here, external system means any piece of code that’s not controlled by React, such as:

  • A timer managed with setInterval() and clearInterval() .
  • An event subscription using window.addEventListener() and window.removeEventListener() .
  • A third-party animation library with an API like animation.start() and animation.reset() .

If you’re not connecting to any external system, you probably don’t need an Effect.

Examples of connecting to an external system

Example 1 of 5 : connecting to a chat server.

In this example, the ChatRoom component uses an Effect to stay connected to an external system defined in chat.js . Press “Open chat” to make the ChatRoom component appear. This sandbox runs in development mode, so there is an extra connect-and-disconnect cycle, as explained here. Try changing the roomId and serverUrl using the dropdown and the input, and see how the Effect re-connects to the chat. Press “Close chat” to see the Effect disconnect one last time.

Effects are an “escape hatch”: you use them when you need to “step outside React” and when there is no better built-in solution for your use case. If you find yourself often needing to manually write Effects, it’s usually a sign that you need to extract some custom Hooks for common behaviors your components rely on.

For example, this useChatRoom custom Hook “hides” the logic of your Effect behind a more declarative API:

Then you can use it from any component like this:

There are also many excellent custom Hooks for every purpose available in the React ecosystem.

Learn more about wrapping Effects in custom Hooks.

Examples of wrapping Effects in custom Hooks

Example 1 of 3 : custom usechatroom hook.

This example is identical to one of the earlier examples, but the logic is extracted to a custom Hook.

Sometimes, you want to keep an external system synchronized to some prop or state of your component.

For example, if you have a third-party map widget or a video player component written without React, you can use an Effect to call methods on it that make its state match the current state of your React component. This Effect creates an instance of a MapWidget class defined in map-widget.js . When you change the zoomLevel prop of the Map component, the Effect calls the setZoom() on the class instance to keep it synchronized:

In this example, a cleanup function is not needed because the MapWidget class manages only the DOM node that was passed to it. After the Map React component is removed from the tree, both the DOM node and the MapWidget class instance will be automatically garbage-collected by the browser JavaScript engine.

You can use an Effect to fetch data for your component. Note that if you use a framework, using your framework’s data fetching mechanism will be a lot more efficient than writing Effects manually.

If you want to fetch data from an Effect manually, your code might look like this:

Note the ignore variable which is initialized to false , and is set to true during cleanup. This ensures your code doesn’t suffer from “race conditions”: network responses may arrive in a different order than you sent them.

You can also rewrite using the async / await syntax, but you still need to provide a cleanup function:

Writing data fetching directly in Effects gets repetitive and makes it difficult to add optimizations like caching and server rendering later. It’s easier to use a custom Hook—either your own or maintained by the community.

What are good alternatives to data fetching in Effects?

Writing fetch calls inside Effects is a popular way to fetch data , especially in fully client-side apps. This is, however, a very manual approach and it has significant downsides:

  • Effects don’t run on the server. This means that the initial server-rendered HTML will only include a loading state with no data. The client computer will have to download all JavaScript and render your app only to discover that now it needs to load the data. This is not very efficient.
  • Fetching directly in Effects makes it easy to create “network waterfalls”. You render the parent component, it fetches some data, renders the child components, and then they start fetching their data. If the network is not very fast, this is significantly slower than fetching all data in parallel.
  • Fetching directly in Effects usually means you don’t preload or cache data. For example, if the component unmounts and then mounts again, it would have to fetch the data again.
  • It’s not very ergonomic. There’s quite a bit of boilerplate code involved when writing fetch calls in a way that doesn’t suffer from bugs like race conditions.

This list of downsides is not specific to React. It applies to fetching data on mount with any library. Like with routing, data fetching is not trivial to do well, so we recommend the following approaches:

  • If you use a framework , use its built-in data fetching mechanism. Modern React frameworks have integrated data fetching mechanisms that are efficient and don’t suffer from the above pitfalls.
  • Otherwise, consider using or building a client-side cache. Popular open source solutions include React Query , useSWR , and React Router 6.4+. You can build your own solution too, in which case you would use Effects under the hood but also add logic for deduplicating requests, caching responses, and avoiding network waterfalls (by preloading data or hoisting data requirements to routes).

You can continue fetching data directly in Effects if neither of these approaches suit you.

Notice that you can’t “choose” the dependencies of your Effect. Every reactive value used by your Effect’s code must be declared as a dependency. Your Effect’s dependency list is determined by the surrounding code:

If either serverUrl or roomId change, your Effect will reconnect to the chat using the new values.

Reactive values include props and all variables and functions declared directly inside of your component. Since roomId and serverUrl are reactive values, you can’t remove them from the dependencies. If you try to omit them and your linter is correctly configured for React, the linter will flag this as a mistake you need to fix:

To remove a dependency, you need to “prove” to the linter that it doesn’t need to be a dependency. For example, you can move serverUrl out of your component to prove that it’s not reactive and won’t change on re-renders:

Now that serverUrl is not a reactive value (and can’t change on a re-render), it doesn’t need to be a dependency. If your Effect’s code doesn’t use any reactive values, its dependency list should be empty ( [] ):

An Effect with empty dependencies doesn’t re-run when any of your component’s props or state change.

If you have an existing codebase, you might have some Effects that suppress the linter like this:

When dependencies don’t match the code, there is a high risk of introducing bugs. By suppressing the linter, you “lie” to React about the values your Effect depends on. Instead, prove they’re unnecessary.

Examples of passing reactive dependencies

Example 1 of 3 : passing a dependency array.

If you specify the dependencies, your Effect runs after the initial render and after re-renders with changed dependencies.

In the below example, serverUrl and roomId are reactive values, so they both must be specified as dependencies. As a result, selecting a different room in the dropdown or editing the server URL input causes the chat to re-connect. However, since message isn’t used in the Effect (and so it isn’t a dependency), editing the message doesn’t re-connect to the chat.

When you want to update state based on previous state from an Effect, you might run into a problem:

Since count is a reactive value, it must be specified in the list of dependencies. However, that causes the Effect to cleanup and setup again every time the count changes. This is not ideal.

To fix this, pass the c => c + 1 state updater to setCount :

Now that you’re passing c => c + 1 instead of count + 1 , your Effect no longer needs to depend on count . As a result of this fix, it won’t need to cleanup and setup the interval again every time the count changes.

If your Effect depends on an object or a function created during rendering, it might run too often. For example, this Effect re-connects after every render because the options object is different for every render:

Avoid using an object created during rendering as a dependency. Instead, create the object inside the Effect:

Now that you create the options object inside the Effect, the Effect itself only depends on the roomId string.

With this fix, typing into the input doesn’t reconnect the chat. Unlike an object which gets re-created, a string like roomId doesn’t change unless you set it to another value. Read more about removing dependencies.

If your Effect depends on an object or a function created during rendering, it might run too often. For example, this Effect re-connects after every render because the createOptions function is different for every render:

By itself, creating a function from scratch on every re-render is not a problem. You don’t need to optimize that. However, if you use it as a dependency of your Effect, it will cause your Effect to re-run after every re-render.

Avoid using a function created during rendering as a dependency. Instead, declare it inside the Effect:

Now that you define the createOptions function inside the Effect, the Effect itself only depends on the roomId string. With this fix, typing into the input doesn’t reconnect the chat. Unlike a function which gets re-created, a string like roomId doesn’t change unless you set it to another value. Read more about removing dependencies.

Under Construction

This section describes an experimental API that has not yet been released in a stable version of React.

By default, when you read a reactive value from an Effect, you have to add it as a dependency. This ensures that your Effect “reacts” to every change of that value. For most dependencies, that’s the behavior you want.

However, sometimes you’ll want to read the latest props and state from an Effect without “reacting” to them. For example, imagine you want to log the number of the items in the shopping cart for every page visit:

What if you want to log a new page visit after every url change, but not if only the shoppingCart changes? You can’t exclude shoppingCart from dependencies without breaking the reactivity rules. However, you can express that you don’t want a piece of code to “react” to changes even though it is called from inside an Effect. Declare an Effect Event with the useEffectEvent Hook, and move the code reading shoppingCart inside of it:

Effect Events are not reactive and must always be omitted from dependencies of your Effect. This is what lets you put non-reactive code (where you can read the latest value of some props and state) inside of them. By reading shoppingCart inside of onVisit , you ensure that shoppingCart won’t re-run your Effect.

Read more about how Effect Events let you separate reactive and non-reactive code.

If your app uses server rendering (either directly or via a framework ), your component will render in two different environments. On the server, it will render to produce the initial HTML. On the client, React will run the rendering code again so that it can attach your event handlers to that HTML. This is why, for hydration to work, your initial render output must be identical on the client and the server.

In rare cases, you might need to display different content on the client. For example, if your app reads some data from localStorage , it can’t possibly do that on the server. Here is how you could implement this:

While the app is loading, the user will see the initial render output. Then, when it’s loaded and hydrated, your Effect will run and set didMount to true , triggering a re-render. This will switch to the client-only render output. Effects don’t run on the server, so this is why didMount was false during the initial server render.

Use this pattern sparingly. Keep in mind that users with a slow connection will see the initial content for quite a bit of time—potentially, many seconds—so you don’t want to make jarring changes to your component’s appearance. In many cases, you can avoid the need for this by conditionally showing different things with CSS.

Troubleshooting

When Strict Mode is on, in development, React runs setup and cleanup one extra time before the actual setup.

This is a stress-test that verifies your Effect’s logic is implemented correctly. If this causes visible issues, your cleanup function is missing some logic. The cleanup function should stop or undo whatever the setup function was doing. The rule of thumb is that the user shouldn’t be able to distinguish between the setup being called once (as in production) and a setup → cleanup → setup sequence (as in development).

Read more about how this helps find bugs and how to fix your logic.

First, check that you haven’t forgotten to specify the dependency array:

If you’ve specified the dependency array but your Effect still re-runs in a loop, it’s because one of your dependencies is different on every re-render.

You can debug this problem by manually logging your dependencies to the console:

You can then right-click on the arrays from different re-renders in the console and select “Store as a global variable” for both of them. Assuming the first one got saved as temp1 and the second one got saved as temp2 , you can then use the browser console to check whether each dependency in both arrays is the same:

When you find the dependency that is different on every re-render, you can usually fix it in one of these ways:

As a last resort (if these methods didn’t help), wrap its creation with useMemo or useCallback (for functions).

If your Effect runs in an infinite cycle, these two things must be true:

  • Your Effect is updating some state.
  • That state leads to a re-render, which causes the Effect’s dependencies to change.

Before you start fixing the problem, ask yourself whether your Effect is connecting to some external system (like DOM, network, a third-party widget, and so on). Why does your Effect need to set state? Does it synchronize with that external system? Or are you trying to manage your application’s data flow with it?

If there is no external system, consider whether removing the Effect altogether would simplify your logic.

If you’re genuinely synchronizing with some external system, think about why and under what conditions your Effect should update the state. Has something changed that affects your component’s visual output? If you need to keep track of some data that isn’t used by rendering, a ref (which doesn’t trigger re-renders) might be more appropriate. Verify your Effect doesn’t update the state (and trigger re-renders) more than needed.

Finally, if your Effect is updating the state at the right time, but there is still a loop, it’s because that state update leads to one of the Effect’s dependencies changing. Read how to debug dependency changes.

The cleanup function runs not only during unmount, but before every re-render with changed dependencies. Additionally, in development, React runs setup+cleanup one extra time immediately after component mounts.

If you have cleanup code without corresponding setup code, it’s usually a code smell:

Your cleanup logic should be “symmetrical” to the setup logic, and should stop or undo whatever setup did:

Learn how the Effect lifecycle is different from the component’s lifecycle.

If your Effect must block the browser from painting the screen, replace useEffect with useLayoutEffect . Note that this shouldn’t be needed for the vast majority of Effects. You’ll only need this if it’s crucial to run your Effect before the browser paint: for example, to measure and position a tooltip before the user sees it.

Navigation Menu

Search code, repositories, users, issues, pull requests..., provide feedback.

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly.

To see all available qualifiers, see our documentation .

  • Notifications You must be signed in to change notification settings

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

autoFocus does not work on Safari mobile #3501

@csantos1113

csantos1113 commented Apr 4, 2019

  • 👀 2 reactions

@Rall3n

Rall3n commented Apr 8, 2019 • edited

Sorry, something went wrong.

csantos1113 commented Apr 9, 2019

  • 👍 2 reactions

Rall3n commented Apr 9, 2019 • edited

  • 👍 4 reactions

@karlingen

karlingen commented Sep 27, 2019

Rall3n commented sep 27, 2019.

  • 👍 15 reactions

csantos1113 commented Oct 2, 2019

@csantos1113

pulkitaggarwal-nagarro-uf-srch commented Oct 20, 2022

  • 👍 1 reaction

@dipanshumahla

dipanshumahla commented May 1, 2023

@damianoc90

damianoc90 commented May 29, 2023

@Hyodori04

Hyodori04 commented Aug 29, 2023

No branches or pull requests

@karlingen

Make React useEffect Hook Not Run on Initial Render

In the world of React, the useEffect hook is like that friend who always shows up, whether you invited them or not.

By default, useEffect runs after the initial render and after every re-render, which is great for many scenarios. But what if you want to skip the party starter and only invoke it on updates?

Specifically, how can we make useEffect not run on initial render but only on subsequent updates?

Let's dive into this topic, exploring ways to tame this enthusiastic hook, ensuring it only runs when you want it to, excluding the initial render.

Understanding useEffect

Before we start tricking useEffect into behaving, let's understand what it does. The useEffect hook lets you perform side effects in functional components.

It's the Swiss Army knife in React's functional components, handling tasks like fetching data, directly interacting with the DOM, setting up subscriptions, and more.

The second argument, the dependency array, is the key to controlling when the effect runs. If the array:

Is absent, the effect runs after every render.

Contains values, the effect runs only when those values change.

Is an empty array [] , the effect runs only once after the initial render.

The Challenge with Initial Render

Sometimes, running an effect on the initial render is unnecessary or undesirable. For instance, you might want to fetch data only in response to a user's action, not right when the component mounts.

Unfortunately, useEffect doesn't come with a built-in "skip initial render" feature. But don't worry, where there's a will (and JavaScript), there's a way.

The Solution: Skipping Initial Render

Here’s a strategy to make useEffect skip its initial invocation and only run on updates.

Step 1: Use a Ref as a Flag

We'll use the useRef hook to keep track of whether the component has mounted. useRef persists values across renders without causing re-renders itself, making it perfect for our needs.

In this approach, we initialize a ref called isFirstRender with true .

Inside useEffect , we check this flag. If it’s the first render, we set it to false and exit early. For subsequent renders (updates), the effect runs as intended.

Why This Works

Step 2: cleanup and beyond.

Remember, effects might also include cleanup functions, especially when dealing with subscriptions, timers, or removing event listeners.

If your effect does cleanup, ensure it doesn't rely on code that skips execution during the first render.

Advanced Use Cases

For more complex scenarios, such as when your component depends on multiple effects with different dependencies, apply this pattern selectively.

Not every useEffect might need to skip its initial run. Evaluate your component's logic and apply this strategy where it truly benefits your application's behavior and performance.

While useEffect doesn't offer a direct way to skip the initial render, the flexibility of React hooks allows us to implement this behavior ourselves.

Using useRef as a simple flag provides a straightforward and efficient method to control the execution of effects, aligning them more precisely with our component's lifecycle and state changes.

This technique, like any other, should be used judiciously. It's a powerful tool in your React arsenal, enabling finer control over component behavior and side effects.

However, always consider the readability and maintainability of your code, especially when working in teams or on large projects.

Remember, the goal is not just to make useEffect do what we want but to create components that are clear, concise, and function as intended. Happy coding!

IMAGES

  1. Safari Not Working on Mac/MacBook, How to Fix?

    safari useeffect not working

  2. Safari Not Working? Here's The Complete Troubleshooting Guide & Fix

    safari useeffect not working

  3. Safari Not Working On iOS 15 On iPhone: How To Fix It

    safari useeffect not working

  4. How to Fix “Safari Not Working on Mac”? 15 Simple Ways

    safari useeffect not working

  5. Top 12 Ways to Fix Safari Not Working on iPhone and iPad

    safari useeffect not working

  6. What to Do When Safari Not Working on iPhone/iPad after Update iOS 16

    safari useeffect not working

VIDEO

  1. Safari is AI Now!

  2. The only regret is the path not taken

  3. How to Fix Safari Slow Download Issues on iPhone || Safari Browser Download Speed Slow

  4. How I became a React developer (not what you expect)

  5. Fix React useEffect running twice in React 18

  6. Learn how to use the useEffect hook in React properly #useEffect #programming #reactjs #webdev

COMMENTS

  1. useEffect triggered by recoil state doesn't work as expected in safari

    I want to trigger input type="file" click when state outside the component has changed.. When updated state is passed as prop and useEffect function is excecuted everything work as expected. When updated state is passed as useRecoilState it seems like it doesn't work (but only in safari) - it triggers useEffect as expected but inputRef.current.click() doesn't work.

  2. Safari Won't Play Videos via React useEffect

    TL;DR. View this example in Safari to see how playing a video via useEffect won't work. If you're attempting to make a video play inside a React effect, use useLayoutEffect.. useEffect vs useLayoutEffect. The React docs have the following tip that calls out when you should use useLayoutEffect vs useEffect:. Unlike componentDidMount or componentDidUpdate, effects scheduled with useEffect ...

  3. When accessing the same route, useEffect is not firing

    When I first access, the API of the useEffect runs normally. However, if I go to another screen and then access the screen again, useEffect does not work. This is the same for useEffect on other screens. Can I run useEffect every time I access the screen? Currently, the dependency is set to [], but if [] is removed at all, the application stops.

  4. React useEffect not triggering: Causes and solutions

    The useEffect hook is triggered when a component is mounted, when a prop changes, or when a state variable changes. The most common causes of the useEffect hook not triggering are: Forgetting to call the useEffect hook in the component's constructor. Using the wrong dependency array in the useEffect hook.

  5. React.useEffect Hook

    But there is one useEffect gotcha that a lot of us keep falling for. The use case Let's start with a simple scenario. We are. React hooks have been around for a while now. Most developers have gotten pretty comfortable with how they work and their common use cases. But there is one useEffect gotcha that a lot of us keep falling for. The use ...

  6. UseEffect and useLayout hooks are not triggering on safari ...

    Safari. How are you deploying your application? (if relevant) No response. Describe the Bug. I am calling Rest Api's in useEffect and useLayout hooks, it's working fine in all browsers, creating issue only on safari browser both on desktop and mobile. Expected Behavior. This should be work fine in safari, as it's working fine in all other browsers.

  7. React Hooks

    Hooks allow function components to have access to state and other React features, such as lifecycle methods. These Hook features were introduced to React version 16.8. One of the interesting things about the Hook features is that they let you use React without classes. This, in turn, helps simplify your

  8. useEffect hook not working right? Here are a couple of things you can

    useEffect uses some advance JavaScript and programming concepts. But, despite being advanced, they are well within the reach of any React developer, with a little bit of time and practice. Let's fix it! Modifying State Directly. If you modify state directly (mutate it) then it can cause problems with re-rendering, but not always.

  9. Calling speak function in useEffect doesn't work on mobile safari

    Fixed this by moving playText out of useEffect, and just calling the function directly in the component body. To make sure it's not constantly running I used a state variable, so if !hasPlayed, play then set hasPlayed to true. Also, noticed that either this or mobile safari causes onEnd to not work. So I just moved that functionality to a timeout.

  10. Bug: element.current.scrollIntoView () not working as expected in

    scrollIntoView api doesn't work inside useEffect, while it fires by onClick. ... but works in other browser like safari) facebook/react#23396 - switch from `yext/react-components`'s Markdown component to our own Markdown component since they will be removing that soon and `yext/react-components` also contains other packages/licenses that we don ...

  11. How the useEffect Hook Works (with Examples)

    A Hundred And One Uses. The useEffect function is like the swiss army knife of hooks. It can be used for a ton of things, from setting up subscriptions to creating and cleaning up timers to changing the value of a ref. One thing it's not good for is making DOM changes that are visible to the user.

  12. A complete guide to the useEffect React Hook

    Editor's note: This article was last updated on 12 October 2023 to add a comparison of the useState and useEffect Hooks, the relationship between the useEffect Hook and React Server Components, and more.. Understanding how the useEffect Hook works is one of the most important concepts for mastering React today. Especially if you have been working with React for several years, it is crucial ...

  13. A Developer's Guide to Using useEffect in Next.js

    Most commonly you'll see useEffect functions with either an empty array, so the hook only runs once, or with variables in the dependency array, to keep a component synchronised. Empty Array. With an empty array, your useEffect only runs on the first render. You might use this for example when fetching data that doesn't depend on any parameters.

  14. How To Call Web APIs with the useEffect Hook in React

    Step 3 — Sending Data to an API. In this step, you'll send data back to an API using the Fetch API and the POST method. You'll create a component that will use a web form to send the data with the onSubmit event handler and will display a success message when the action is complete.

  15. useEffect

    The cleanup function runs not only during unmount, but before every re-render with changed dependencies. Additionally, in development, React runs setup+cleanup one extra time immediately after component mounts. If you have cleanup code without corresponding setup code, it's usually a code smell: useEffect(() => {.

  16. autoFocus does not work on Safari mobile #3501

    @karlingen Yes, we have. There was a comment about it in a ticket for WebKit. The comment was created March 2019, and states the following: "We (Apple) like the current behavior and do not want programmatic focus to bring up the keyboard when [...] the programmatic focus was not invoked in response to a user gesture."

  17. Make React useEffect Hook Not Run on Initial Render

    Not every useEffect might need to skip its initial run. Evaluate your component's logic and apply this strategy where it truly benefits your application's behavior and performance. Conclusion. While useEffect doesn't offer a direct way to skip the initial render, the flexibility of React hooks allows us to implement this behavior ourselves.

  18. useEffect not running when state changes

    Chosen pics are added to asyncstorage. Go back to MyPics page. Page re-renders on entry, checks asyncstorage with useEffect, updates page. Problem: useEffect does not re-check asyncstorage on re-entry to screen, which it should. Only way to do that is to add in state as a second argument to useEffect. But that causes a loop. Surely this is a ...

  19. Safari not updating my useState boolean value

    Yes it gets called once login is successful And it works fine on other browsers. The state gets updated. But on Safari on Mac, it doesn't update the state. But it does on chrome on macOs but Safari and chrome on ios, it doesn't work -