skip to Main Content

I encountered the following code in a project, where a custom string is created as a dependency for a useEffect hook:

Defined refreshKey

const refreshKey = [
    pageIndex,
    filterActive,
    viewSetting,
    itemType,
    sortingValue,
    userLanguage,
    sortOrder,
    window.location.href,
    searchQuery
].join("_")

The usage then:

useEffect(() => {
    // Fetch or update data when any of the dependencies change
    fetchData();

    // The effect depends on the custom `refreshKey`
}, [refreshKey]);

My concerns are:

  1. Is this the correct way to use a custom string as a dependency in useEffect?

  2. Would it be safer or more reliable to list each state variable individually in the dependency array instead of combining them into a single string?

  3. Could this cause unexpected behaviour of the component?

2

Answers


  1. It’s not recommended to do so. refreshKey will be new on every render, it means the useEffect runs on every render, which is somtimes unnecessary.

    And yes, to list each state variable individually in the dependency array is always a better choice.

    useEffect(() => {
        // Fetch or update data when any of the dependencies change
        fetchData();
    
        // The effect depends on individual state variables
    }, [pageIndex, filterActive, viewSetting, itemType, sortingValue, userLanguage, sortOrder, searchQuery]);
    
    Login or Signup to reply.
    1. It’s also a correct usage.

    Regarding whether you should do that or not:

    It matters if ‘refreshKey’ will be passed in the multiple hooks. (It’s more about performance, but in my opinion, I don’t see any reason to do it because it would provide only a small advantage in cases where the number of hooks including this is not very large. )

    Dependencies are checked this way, so the for loop will be completed when all items are checked. Also, for every item in the dependencies, Object.is will be called.

    for (let i = 0; i < prevDeps.length && i < nextDeps.length; i++) {
        if (Object.is(nextDeps[i], prevDeps[i])) {
          continue;
        }
        return false;
      }
      return true;
    

    We can also consider it as following the ‘DRY’ principle, but in my opinion, in this case, we don’t need to use join. We can create an array and pass it as a second argument instead.

    1. Unfortunately, I can’t think of any specific case that I can imagine off the top of my head right now. I can only say that if you used something incorrectly, it doesn’t matter if it’s in the dependencies or elsewhere—you will get an error.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search