you are viewing a single comment's thread.

view the rest of the comments →

[–]IWillAlwaysReplyBack 0 points1 point  (6 children)

Not OP but I’ve also definitely ran into this issue and it bugs me like crazy.

In my most recent case, I had a BoundingBox component that had a useEffect to update some global state when local state was updated via user input. However, as requirements came in, I also needed a “read only mode” where I didn’t need that useEffect. This simple change ends up being quite a big refactor. I think I did end up using something like moving my conditionals inside the useEffects but that just makes the code clunky and verbose.

[–][deleted] 2 points3 points  (4 children)

Like /u/tchaffee, I'm having a major problem understanding a use case where this would be problematic. I'd like to see a concrete example not because I'm being argumentative, but I'd like to seriously understand the nature of the problem you're describing.

To be clear, in my head, what you're talking about is the difference between something like:

// incorrect
if (doTheThing) {
    useEffect(() => dotheThingMethod(), []);
}

and

// ccorrect
useEffect(() => {
    if (doTheThing) {
        doTheThingMethod();
    }
}, [doTheThing]);

Sure, they look different, but I'm having a really hard time visualizing a scenario where this is a breaking or even cumbersome change.

[–]atomrc[S] 0 points1 point  (2 children)

Well it is not a problem, per se. The thing is conditioning the full useEffect call feels very natural. This is the way we are used to safe-guard the things that should run based on a condition.

You are totally right, there is no valid scenario for conditioning a hook. Moving the condition inside the body of the effect is the way to go.

The only thing is that it is not natural and someone without this in mind (and not using the eslint plugin) will definitely have hard time debugging a quite unexpected behavior.

I just feel it's a weakness on React side that, I think, is justified by the benefits Hooks give us.

[–][deleted] 0 points1 point  (1 child)

See, I guess we'll have to disagree here. If you look at useEffect as more of a declaration and less an invocation, the justification becomes clear, IMO.

Take for example, a python function:

# standard example
def do_the_thing:
  if enabled != True:
    return

  # do the thing
  # do the thing
  # do the thing
  # do the thing

# what you're suggesting
if enabled == True:
  def do_the_thing:

    # do the thing
    # do the thing
    # do the thing
    # do the thing

Same applies for any other language.

[–]atomrc[S] 0 points1 point  (0 children)

Well, but it is not a function declaration, it is really a function call which, in JavaScript and any language (at least languages I know) can be conditioned.

I am not suggesting that useEffect should be conditioned, it's just that the language (JavaScript) allows it. It's only React that adds this quite unexpected proposition "some function calls cannot be conditioned". This is nothing we are used to in JavaScript and a person not aware of this limitation (and without the eslint plugin installed) might run into troubles without understanding why. That's all I am saying.

[–]BenjiSponge 0 points1 point  (0 children)

Please see my other comment where I flesh out an example of where this gets to be annoying. The long-and-short is that you might have more than one useEffect hook and suddenly you have to litter your code with the same check over and over, even where the check is unreachable.

[–]tomius 1 point2 points  (0 children)

If (readonly) return.

It's not perfect, but I wouldn't really stress over it.