solidjs-community / eslint-plugin-solid

Solid-specific linting rules for ESLint.
MIT License
216 stars 26 forks source link

Warn on early returns from a component #24

Closed joshwilsonvu closed 2 years ago

joshwilsonvu commented 2 years ago

Describe the need As mentioned in this thread, it's surprising at first glance to many devs coming from React that conditional early returns in components don't work as expected. An example:

import { render } from "solid-js/web";
import { createSignal } from "solid-js";

function Counter() {
  const [count, setCount] = createSignal(0);

  setInterval(() => setCount(count() + 1), 1000);

  if (count() > 2) return <div>Larger than 2</div>;

  return <div>Count: {count()}</div>;
}

render(() => <Counter />, document.getElementById("app")!);

Because a component only runs once, this component will only ever render Larger than 2. The correct solution is to move the condition into a reactive JSX context. solid/reactivity already catches if (count() > 2), but doesn't give specific feedback and doesn't handle cases where the condition is not reactive.

Suggested Solution There should be a new lint rule, solid/components-return-once, that enforces that any function that returns JSX at any point should have only one return statement that is the last statement of the function body. Anything else is an early return in a component. Also, the return value cannot be a ternary or other conditional expression; these are only reactive inside JSX like a fragment.

Fixes could be provided in certain cases:

  1. An early return directly before the final return could be transformed into a Show fallback.
  2. A returned ternary could be transformed into a ternary inside a JSX fragment or into a Show. Since it's not clear which is the fallback and which is the children, the first option could be better.

Possible Alternatives People are confused and are asking for a lint rule directly, and a lint rule is the best fit for this kind of warning, so there's not really a workaround.

joshwilsonvu commented 2 years ago

Added in v0.6.0.