0

I am relatively new to React, so probably it will be an easy answer for some of you.

I have bumped into a little problem, I have solved it, but it doesn't seem to be perfect as React Eslint is not happy.

My web-app is using React-Redux at the front and Node-Express-Mongo at the back. So, I have a functional component (screen/page), and whenever logged in user visits it, it needs to update user data state in Redux store to make sure it matches current data in database.

However, not registered and not logged in users also can visit that page, then obviously that database check is not needed.

I get user data as userInfo object from Redux:

const userLogin = useSelector((state) => state.userLogin);
const { loading: loadingUser, error: errorUser, userInfo } = userLogin;

Then, when component renders useEffect() hook shoots, I dispatch an action to get user data from backend (DB) using JWT token.

useEffect(() => {
    //update user details in case if access to restricted services changes
    if (userInfo && userInfo.token) {
      dispatch(refreshUser(userInfo.token));
    }
    // eslint-disable-next-line
  }, []);

As you can see I kept dependency array empty, and disabled it for eslint to keep Mr Eslint happy.

So far this is the only way I can make it work. If I put userInfo into dependency array - it creates infinite loop, because as we know {}==={} always returns false.

If I get rid of userInfo from useEffect() and keep just userInfo.token, but then it creates an error userInfo is undefined whenever user is not logged in

Of course I can populate Redux store with some initial state of empty userInfo or empty userInfo.token, but that seems to be unnecessary hassle. I also tried to put useEffect inside if (userInfo){} statement, but that was just silly, as useEffect() should stay at the top level...

As it is now, it does what I need it to do - runs just once as the component (page) loads.

So my question is: Is it OK to leave it like that or there must be some elegant solution?

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
waway
  • 38
  • 6
  • 2
    `[userInfo]` in your dependency array will trigger recursion, because the useEffect hook itself updates `userInfo`. If you want to check `userInfo.token` with `userInfo` being potentially undefined, use `userInfo?.token` (optional chaining). – Terry Feb 19 '22 at 00:01
  • Another solution is to use the null object pattern, e.g., a `userInfo` that's *defined*, but doesn't contain a token. Depending on requirements this can confer other benefits as well. – Dave Newton Feb 19 '22 at 00:01
  • @Terry Thanks for this syntax, useful to know. However in my case it solves only half a problem, it prevents infinite loop, but I would still need to include userInfo.token in dependency array and in case of non-logged-in user it will throw an error about userInfo is null. – waway Feb 19 '22 at 07:34
  • @DaveNewton In case of non-logged-in user it will throw an error about userInfo is null. Thanks for your comment. I think my best bet is to keep it as it is. – waway Feb 19 '22 at 07:36
  • 1
    I didn't say "use `null`", I said "use the null-object pattern" (https://en.wikipedia.org/wiki/Null_object_pattern) where there's a user object that represents a not-logged-in user. – Dave Newton Feb 19 '22 at 13:26

0 Answers0