0

I have a certain query string I am looking for and when that gets passed on page loading I need to update my user's status to "premium". I have:

  useEffect(() => {
    const queryString = require('query-string');
    const values = queryString.parse(window.location.search);
    console.log('before' + user.premium);
    if (values.premium !== ''){
      setUser({...user, premium: true});
    }
    console.log('after' + user.premium);
  }, []);

I am using React functional components and my user is an object that contains many other values, in addition to "premium" key. From what I understand, passing the empty array [] will cause useEffect to run only on page load. Doing so, however, I get an error:

React Hook useEffect has a missing dependency: 'user'.. BUT, when I include user in that array, the page continually reloads (since I am updating the value of it). I've also tried passing in setUser and that didn't work.

hgb123
  • 13,869
  • 3
  • 20
  • 38
user_78361084
  • 3,538
  • 22
  • 85
  • 147

1 Answers1

1

You can pass properties of object as dependencies for useEffect. I have created a working sandbox here.

Also, don't worry to much about the eslint rule react-hooks/exhaustive-deps, view it as more of a guideline and don't be afraid to add a eslint-disable-next-line if it is pushing you to add dependencies that you don't think should be added.

import React, { useEffect, useState } from "react";

export default function App() {
  const [user, setUser] = useState({ count: 0, premium: false });

  useEffect(() => {
    console.log("when component mounts");
  }, []);

  useEffect(() => {
    console.log("when component updates");
  });

  useEffect(() => {
    console.log("when premium changes");
  }, [user.premium]);

  return (
    <div>
      <p>Count: {user.count}</p>
      <p>Premium: {user.premium}</p>
      <button
        onClick={() => setUser((prev) => ({ ...prev, count: prev.count + 1 }))}
      >
        Increment Count
      </button>
      <button
        onClick={() => setUser((prev) => ({ ...prev, premium: !prev.premium }))}
      >
        Toggle premium
      </button>
    </div>
  );
}

Alex Mckay
  • 3,463
  • 16
  • 27
  • On the other hand, ignoring the eslint rule `react-hooks/exhaustive-deps` will usually lead to subtle bugs due to stale references being kept. There's always a way to satisfy the exhaustive dependencies, even if it's sometimes a little more verbose than you might like. – Patrick Roberts Aug 25 '20 at 04:37
  • With all due respect, unit tests are better at discovering dependency errors than a linter. Making code overly verbose to appease a linter can harm readability and maintainability of code without actually providing a great deal of confidence. – Alex Mckay Aug 31 '20 at 02:04