Skip to content

[feat] Disallow a function wrapped in useCallback yet only used in useEffect and only in one useEffectΒ #1278

@SukkaW

Description

@SukkaW

Problem Description

This code should be considered invalid:

const Component = () => {
  const doSomeTask = useCallback(() => { /***/ }, [/***/]);
  useEffect(() => {
    // some condition
    doSomeTask();
  }, [doSomeTask]);
  return <div />;
};

This is because doSomeTask is only used inside one useEffect, thus the entire function declaration should be moved inside this one useEffect instead (and merge the useCallback's dependency array into useEffect's dependency array):

// Correct version of the above code

const Component = () => {
  useEffect(() => {
    const doSomeTask = () => { /***/ };

    // some condition
    doSomeTask();
  }, [/***/]);

  return <div />;
};

However, when the function wrapped by useCallback is used more than once (i.e. two useEffect), then it should be valid. E.g., those two examples should both be valid.

// useCallback in two useEffect

const Component = () => {
  const doSomeTask = useCallback(() => { /***/ }, [/***/]);

  useEffect(() => {
    // some condition
    doSomeTask();
  }, [doSomeTask]);

  useEffect(() => {
    // some condition
    doSomeTask();
  }, [doSomeTask]);

  return <div />;
};
// useCallback in both useEffect and JSX

const Component = () => {
  const doSomeTask = useCallback(() => { /***/ }, [/***/]);

  useEffect(() => {
    // some condition
    doSomeTask();
  }, [doSomeTask]);

  return <div onClick={doSomeTask} />;
};

Callback ref, by its nature, should be valid as well:

// useCallback in two useEffect

const Component = () => {
  const doSomeTask = useCallback(() => { /***/ }, [/***/]);

  return <div ref={doSomeTask} />;
};

We will allow useCallback with JSX's event handlers as well:

// useCallback in two useEffect

const Component = () => {
  const doSomeTask = useCallback(() => { /***/ }, [/***/]);

  return <div onClick={doSomeTask} />;
};

Alternative Solutions

N/A

Feature Details

Maybe we could call this rule: no-useless-use-callback-for-use-effect

Examples

See above.

Evaluation Checklist

  • I have had problems that this feature would solve
  • I could not find a way to solve the problem with existing features or workarounds
  • I have thought very hard about potential edge cases and downsides, and they are acceptable
  • I think the feature is well-defined and would provide clear value to users

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions