Reputation: 1003
I frequently pass properties to Solid components that are read-only for dependency injection of singleton services. See the simplified example below. However the SolidJS lint rules give me errors like: The reactive variable 'props.firestore' should be used within JSX, a tracked scope (like createEffect), or inside an event handler function.
It seems totally reasonable to have some readonly props like this. Am I misusing props in SolidJS or not understanding something? Or are the ESLint rules not sophisticated enough? I can disable the lint warnings but don't want to do that if I'm doing something wrong here.
export const DocumentView = (props: { firestore: Firestore }) => {
const query = query(collection(props.firestore), "my-collection");
const [docs, setDocs] = createSignal([]);
const unsubscribeQuery = onSnapshot(query, (snapshot) => {
setDocs(() => snapshot);
});
onCleanup(() => unsubscribeQuery());
return (
<div>
<For each={docs}>{(i) => <p>{i}</p>}</For>{" "}
</div>
);
};
Upvotes: 1
Views: 1171
Reputation: 13698
When the components compiled, props becomes the function arguments and they are passed as is. So, if you pass readonly values to a component, they will remain readonly.
import { Component } from 'solid-js';
export const DocumentView: Component<any> = (props) => {
return (
<div>{JSON.stringify(props.o)}</div>
);
};
import { template as _$template } from "solid-js/web";
import { insert as _$insert } from "solid-js/web";
const _tmpl$ = /*#__PURE__*/_$template(`<div></div>`, 2);
import { Component } from 'solid-js';
export const DocumentView = props => {
return (() => {
const _el$ = _tmpl$.cloneNode(true);
_$insert(_el$, () => JSON.stringify(props.o));
return _el$;
})();
};
Now, the problem with your code is using untracked reactive variables. By untract, we mean its dependencies can not be tracked by the Solid's runtime.
Solid tracks effects by creating a data structure where the inner scope will be owned by an outer scope, and this chain goes all the way up to the render
function. That is why you get an error like below when you create effects outside this hierarchy.
SolidJS: "computations created outside
a `createRoot` or `render` will never be disposed."
This is for preventing memory leaks by releasing any resource created by an effect. You can read more about owners:
https://www.solidjs.com/docs/latest#runwithowner
However this check targets the untracked effects, not signals. So you can access signals anywhere, doesn't matter scope is tracked or not:
The related eslint rule limits the accessing of signals to the tracked scopes, probably as a safety measure.
"The reactive variable '{{name}}' should be used within JSX,
a tracked scope (like createEffect),
or inside an event handler function.",
This means you can use signal values inside a tracked scope. So, disabling the rule should not have any effect on how your components run.
Upvotes: 0