Skip to content

Commit 0689640

Browse files
authored
Merge pull request #83 from solidjs-community/feature/static-props
Allow using 'static*' props outside tracked scopes, but forbid passing reactive variables to them in the caller
2 parents 52ecd3c + 5380933 commit 0689640

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

docs/reactivity.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,9 @@ const result = indexArray(array, (item) => {
387387
item();
388388
});
389389

390+
const [signal] = createSignal();
391+
let el = <Component staticProp={signal()} />;
392+
390393
```
391394

392395
### Valid Examples
@@ -726,6 +729,15 @@ function Component(props) {
726729
);
727730
}
728731

732+
function Component(props) {
733+
const value = props.staticValue;
734+
}
735+
736+
function Component() {
737+
const staticValue = () => props.value;
738+
const value = staticValue();
739+
}
740+
729741
```
730742
<!-- AUTO-GENERATED-CONTENT:END -->
731743

src/rules/reactivity.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ const rule: TSESLint.RuleModule<MessageIds, []> = {
547547
});
548548
} else if (
549549
parent.property.type === "Identifier" &&
550-
/^(?:initial|default)[A-Z]/.test(parent.property.name)
550+
/^(?:initial|default|static)[A-Z]/.test(parent.property.name)
551551
) {
552552
// We're using a prop with a name that starts with `initial` or
553553
// `default`, like `props.initialCount`. We'll refrain from warning
@@ -832,6 +832,18 @@ const rule: TSESLint.RuleModule<MessageIds, []> = {
832832
// rule will warn later.
833833
// TODO: add some kind of "anti- tracked scope" that still warns but enhances the error
834834
// message if matched.
835+
} else if (
836+
node.parent?.type === "JSXAttribute" &&
837+
node.parent.name?.type === "JSXIdentifier" &&
838+
/^static[A-Z]/.test(node.parent.name.name) &&
839+
node.parent.parent?.type === "JSXOpeningElement" &&
840+
node.parent.parent.name.type === "JSXIdentifier" &&
841+
!isDOMElementName(node.parent.parent.name.name)
842+
) {
843+
// A caller is passing a value to a prop prefixed with `static` in a component, i.e.
844+
// `<Box staticName={...} />`. Since we're considering these props as static in the component
845+
// we shouldn't allow passing reactive values to them, as this isn't just ignoring reactivity
846+
// like initial*/default*; this is disabling it altogether as a convention. Do nothing.
835847
} else if (
836848
node.parent?.type === "JSXAttribute" &&
837849
node.parent.name.name === "ref" &&

test/rules/reactivity.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,14 @@ export const cases = run("reactivity", rule, {
279279
}}</div>
280280
);
281281
}`,
282+
// static* prefix for props
283+
`function Component(props) {
284+
const value = props.staticValue;
285+
}`,
286+
`function Component() {
287+
const staticValue = () => props.value;
288+
const value = staticValue();
289+
}`,
282290
],
283291
invalid: [
284292
// Untracked signals
@@ -746,5 +754,12 @@ export const cases = run("reactivity", rule, {
746754
});`,
747755
errors: [{ messageId: "untrackedReactive", line: 4 }],
748756
},
757+
// static* prefix for props
758+
{
759+
code: `
760+
const [signal] = createSignal();
761+
let el = <Component staticProp={signal()} />;`,
762+
errors: [{ messageId: "untrackedReactive" }],
763+
},
749764
],
750765
});

0 commit comments

Comments
 (0)