solidjs-community / eslint-plugin-solid

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

Reactivity rule with wrappers #40

Closed shishkin closed 1 year ago

shishkin commented 1 year ago

I've created a function wrapper that combines useContext with createEffect to deal with optionality of the context as syntax sugar:

type MyValue = ...;
const MyContext = createContext<Accessor<MyValue | undefined>>();
const useMyContext = () => useContext(MyContext);

const withMyValue = (f: (v: MyValue) => void) => createEffect(() => {
  const val = useMyContext()?.();
  if (val) f(val);
});

function MyComponent() {
  withMyValue(val => console.log("Value:", val));
  return <></>;
}

Now, I get This function should be passed to a tracked scope ... when I use the withMyValue wrapper inside the component. From the rule description I understood that the rule should correctly identify that the call to reactivity is inside a call to createEffect which is tracked.

What am I missing?

joshwilsonvu commented 1 year ago

Right now, the reactivity rule matches custom hooks by name, specifically names beginning with use or create, rather than fully analyzing the implementation. This is because often, the custom hook is imported from another file, so the implementation isn't available.

I suggest renaming withMyValue to useMyValue so the rule will be permissive about where reactivity is allowed. You could also disable the warning with a // eslint-disable-next-line solid/reactivity comment, but you'll have to do that each time you use the hook.

Thanks for the question!

shishkin commented 1 year ago

Thanks @joshwilsonvu, renaming the wrapper helped!

zjullion commented 1 year ago

I know this is closed - but is there any possibility of allowing some type of config / overrides file to specify function names that should be considered reactive?

My use case is a little bit weird:

import { css } from 'goober'
import { createMemo } from 'solid-js'
import { styled as solidStyled } from 'solid-styled-components'

const createClassMemo = (tag: TemplateStringsArray, ...props: Array<string | number>) =>
  createMemo(() => css(tag, ...props))

export const styled = {
  ...solidStyled,
  createClassMemo,
}

This custom hook is just used to ensure css styles are reactive. I'm essentially redefining styled from solid-styled-components, because prettier looks for the identifier "styled" specifically to apply nice CSS formatting to the string template. Since eslint-plugin-solid is looking for functions that begin with use or create, I'm kinda stuck between a rock and a hard place - I either can't get nice formatting, or I get a lot of reactivity warnings.