|
|
|
|
@@ -585,6 +585,29 @@ const allTests = {
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Valid: useEffectEvent can be called in custom effect hooks configured via ESLint settings
|
|
|
|
|
function MyComponent({ theme }) {
|
|
|
|
|
const onClick = useEffectEvent(() => {
|
|
|
|
|
showNotification(theme);
|
|
|
|
|
});
|
|
|
|
|
useMyEffect(() => {
|
|
|
|
|
onClick();
|
|
|
|
|
});
|
|
|
|
|
useServerEffect(() => {
|
|
|
|
|
onClick();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
settings: {
|
|
|
|
|
'react-hooks': {
|
|
|
|
|
additionalEffectHooks: '(useMyEffect|useServerEffect)',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
syntax: 'flow',
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Component syntax version
|
|
|
|
|
// Valid: useEffectEvent can be called in custom effect hooks configured via ESLint settings
|
|
|
|
|
component MyComponent(theme: any) {
|
|
|
|
|
const onClick = useEffectEvent(() => {
|
|
|
|
|
showNotification(theme);
|
|
|
|
|
});
|
|
|
|
|
@@ -618,6 +641,24 @@ const allTests = {
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
syntax: 'flow',
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Component syntax version
|
|
|
|
|
// Valid because functions created with useEffectEvent can be called in a useEffect.
|
|
|
|
|
component MyComponent(theme: any) {
|
|
|
|
|
const onClick = useEffectEvent(() => {
|
|
|
|
|
showNotification(theme);
|
|
|
|
|
});
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
onClick();
|
|
|
|
|
});
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
|
onClick();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Valid because functions created with useEffectEvent can be passed by reference in useEffect
|
|
|
|
|
@@ -644,6 +685,34 @@ const allTests = {
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
syntax: 'flow',
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Component syntax version
|
|
|
|
|
// Valid because functions created with useEffectEvent can be passed by reference in useEffect
|
|
|
|
|
// and useEffectEvent.
|
|
|
|
|
component MyComponent(theme: any) {
|
|
|
|
|
const onClick = useEffectEvent(() => {
|
|
|
|
|
showNotification(theme);
|
|
|
|
|
});
|
|
|
|
|
const onClick2 = useEffectEvent(() => {
|
|
|
|
|
debounce(onClick);
|
|
|
|
|
debounce(() => onClick());
|
|
|
|
|
debounce(() => { onClick() });
|
|
|
|
|
deboucne(() => debounce(onClick));
|
|
|
|
|
});
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
let id = setInterval(() => onClick(), 100);
|
|
|
|
|
return () => clearInterval(onClick);
|
|
|
|
|
}, []);
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
|
let id = setInterval(() => onClick(), 100);
|
|
|
|
|
return () => clearInterval(onClick);
|
|
|
|
|
}, []);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
function MyComponent({ theme }) {
|
|
|
|
|
@@ -656,6 +725,20 @@ const allTests = {
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
syntax: 'flow',
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Component syntax version
|
|
|
|
|
component MyComponent(theme: any) {
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
onClick();
|
|
|
|
|
});
|
|
|
|
|
const onClick = useEffectEvent(() => {
|
|
|
|
|
showNotification(theme);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
function MyComponent({ theme }) {
|
|
|
|
|
@@ -673,6 +756,25 @@ const allTests = {
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
syntax: 'flow',
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Component syntax version
|
|
|
|
|
component MyComponent(theme: any) {
|
|
|
|
|
// Can receive arguments
|
|
|
|
|
const onEvent = useEffectEvent((text) => {
|
|
|
|
|
console.log(text);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
onEvent('Hello world');
|
|
|
|
|
});
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
|
onEvent('Hello world');
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Valid because functions created with useEffectEvent can be called in useLayoutEffect.
|
|
|
|
|
@@ -689,6 +791,24 @@ const allTests = {
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
syntax: 'flow',
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Component syntax version
|
|
|
|
|
// Valid because functions created with useEffectEvent can be called in useLayoutEffect.
|
|
|
|
|
component MyComponent(theme: any) {
|
|
|
|
|
const onClick = useEffectEvent(() => {
|
|
|
|
|
showNotification(theme);
|
|
|
|
|
});
|
|
|
|
|
useLayoutEffect(() => {
|
|
|
|
|
onClick();
|
|
|
|
|
});
|
|
|
|
|
React.useLayoutEffect(() => {
|
|
|
|
|
onClick();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Valid because functions created with useEffectEvent can be called in useInsertionEffect.
|
|
|
|
|
@@ -705,6 +825,24 @@ const allTests = {
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
syntax: 'flow',
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Component syntax version
|
|
|
|
|
// Valid because functions created with useEffectEvent can be called in useInsertionEffect.
|
|
|
|
|
component MyComponent(theme) {
|
|
|
|
|
const onClick = useEffectEvent(() => {
|
|
|
|
|
showNotification(theme);
|
|
|
|
|
});
|
|
|
|
|
useInsertionEffect(() => {
|
|
|
|
|
onClick();
|
|
|
|
|
});
|
|
|
|
|
React.useInsertionEffect(() => {
|
|
|
|
|
onClick();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Valid because functions created with useEffectEvent can be passed by reference in useLayoutEffect
|
|
|
|
|
@@ -739,6 +877,42 @@ const allTests = {
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
syntax: 'flow',
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Component syntax version
|
|
|
|
|
// Valid because functions created with useEffectEvent can be passed by reference in useLayoutEffect.
|
|
|
|
|
// and useInsertionEffect.
|
|
|
|
|
component MyComponent(theme: any) {
|
|
|
|
|
const onClick = useEffectEvent(() => {
|
|
|
|
|
showNotification(theme);
|
|
|
|
|
});
|
|
|
|
|
const onClick2 = useEffectEvent(() => {
|
|
|
|
|
debounce(onClick);
|
|
|
|
|
debounce(() => onClick());
|
|
|
|
|
debounce(() => { onClick() });
|
|
|
|
|
deboucne(() => debounce(onClick));
|
|
|
|
|
});
|
|
|
|
|
useLayoutEffect(() => {
|
|
|
|
|
let id = setInterval(() => onClick(), 100);
|
|
|
|
|
return () => clearInterval(onClick);
|
|
|
|
|
}, []);
|
|
|
|
|
React.useLayoutEffect(() => {
|
|
|
|
|
let id = setInterval(() => onClick(), 100);
|
|
|
|
|
return () => clearInterval(onClick);
|
|
|
|
|
}, []);
|
|
|
|
|
useInsertionEffect(() => {
|
|
|
|
|
let id = setInterval(() => onClick(), 100);
|
|
|
|
|
return () => clearInterval(onClick);
|
|
|
|
|
}, []);
|
|
|
|
|
React.useInsertionEffect(() => {
|
|
|
|
|
let id = setInterval(() => onClick(), 100);
|
|
|
|
|
return () => clearInterval(onClick);
|
|
|
|
|
}, []);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
invalid: [
|
|
|
|
|
{
|
|
|
|
|
@@ -1525,6 +1699,22 @@ const allTests = {
|
|
|
|
|
`,
|
|
|
|
|
errors: [useEffectEventError('onClick', true)],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
syntax: 'flow',
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Component syntax version
|
|
|
|
|
// Invalid: useEffectEvent should not be callable in regular custom hooks without additional configuration
|
|
|
|
|
component MyComponent() {
|
|
|
|
|
const onClick = useEffectEvent(() => {
|
|
|
|
|
showNotification(theme);
|
|
|
|
|
});
|
|
|
|
|
useCustomHook(() => {
|
|
|
|
|
onClick();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
errors: [useEffectEventError('onClick', true)],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Invalid: useEffectEvent should not be callable in hooks not matching the settings regex
|
|
|
|
|
@@ -1544,6 +1734,27 @@ const allTests = {
|
|
|
|
|
},
|
|
|
|
|
errors: [useEffectEventError('onClick', true)],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
syntax: 'flow',
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Component syntax version
|
|
|
|
|
// Invalid: useEffectEvent should not be callable in hooks not matching the settings regex
|
|
|
|
|
component MyComponent(theme: any) {
|
|
|
|
|
const onClick = useEffectEvent(() => {
|
|
|
|
|
showNotification(theme);
|
|
|
|
|
});
|
|
|
|
|
useWrongHook(() => {
|
|
|
|
|
onClick();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
settings: {
|
|
|
|
|
'react-hooks': {
|
|
|
|
|
additionalEffectHooks: 'useMyEffect',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
errors: [useEffectEventError('onClick', true)],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
function MyComponent({ theme }) {
|
|
|
|
|
@@ -1555,6 +1766,19 @@ const allTests = {
|
|
|
|
|
`,
|
|
|
|
|
errors: [useEffectEventError('onClick', false)],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
syntax: 'flow',
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Component syntax version
|
|
|
|
|
component MyComponent(theme: any) {
|
|
|
|
|
const onClick = useEffectEvent(() => {
|
|
|
|
|
showNotification(theme);
|
|
|
|
|
});
|
|
|
|
|
return <Child onClick={onClick}></Child>;
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
errors: [useEffectEventError('onClick', false)],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Invalid because useEffectEvent is being passed down
|
|
|
|
|
@@ -1566,6 +1790,19 @@ const allTests = {
|
|
|
|
|
`,
|
|
|
|
|
errors: [{...useEffectEventError(null, false), line: 4}],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
syntax: 'flow',
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Component syntax version
|
|
|
|
|
// Invalid because useEffectEvent is being passed down
|
|
|
|
|
component MyComponent(theme: any) {
|
|
|
|
|
return <Child onClick={useEffectEvent(() => {
|
|
|
|
|
showNotification(theme);
|
|
|
|
|
})} />;
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
errors: [{...useEffectEventError(null, false), line: 5}],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// This should error even though it shares an identifier name with the below
|
|
|
|
|
@@ -1601,6 +1838,43 @@ const allTests = {
|
|
|
|
|
{...useEffectEventError('onClick', true), line: 15},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
syntax: 'flow',
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Component syntax version
|
|
|
|
|
// This should error even though it shares an identifier name with the below
|
|
|
|
|
component MyComponent(theme: any) {
|
|
|
|
|
const onClick = useEffectEvent(() => {
|
|
|
|
|
showNotification(theme)
|
|
|
|
|
});
|
|
|
|
|
return <Child onClick={onClick} />
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The useEffectEvent function shares an identifier name with the above
|
|
|
|
|
component MyOtherComponent(theme: any) {
|
|
|
|
|
const onClick = useEffectEvent(() => {
|
|
|
|
|
showNotification(theme)
|
|
|
|
|
});
|
|
|
|
|
return <Child onClick={() => onClick()} />
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The useEffectEvent function shares an identifier name with the above
|
|
|
|
|
component MyLastComponent(theme: any) {
|
|
|
|
|
const onClick = useEffectEvent(() => {
|
|
|
|
|
showNotification(theme)
|
|
|
|
|
});
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
onClick(); // No error here, errors on all other uses
|
|
|
|
|
onClick;
|
|
|
|
|
})
|
|
|
|
|
return <Child />
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
errors: [
|
|
|
|
|
{...useEffectEventError('onClick', false), line: 8},
|
|
|
|
|
{...useEffectEventError('onClick', true), line: 16},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
const MyComponent = ({ theme }) => {
|
|
|
|
|
@@ -1625,6 +1899,21 @@ const allTests = {
|
|
|
|
|
`,
|
|
|
|
|
errors: [{...useEffectEventError('onClick', false), line: 7}],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
syntax: 'flow',
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Component syntax version
|
|
|
|
|
// Invalid because onClick is being aliased to foo but not invoked
|
|
|
|
|
component MyComponent(theme: any) {
|
|
|
|
|
const onClick = useEffectEvent(() => {
|
|
|
|
|
showNotification(theme);
|
|
|
|
|
});
|
|
|
|
|
let foo = onClick;
|
|
|
|
|
return <Bar onClick={foo} />
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
errors: [{...useEffectEventError('onClick', false), line: 8}],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Should error because it's being passed down to JSX, although it's been referenced once
|
|
|
|
|
@@ -1641,6 +1930,24 @@ const allTests = {
|
|
|
|
|
`,
|
|
|
|
|
errors: [useEffectEventError('onClick', false)],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
syntax: 'flow',
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Component syntax version
|
|
|
|
|
// Should error because it's being passed down to JSX, although it's been referenced once
|
|
|
|
|
// in an effect
|
|
|
|
|
component MyComponent(theme: any) {
|
|
|
|
|
const onClick = useEffectEvent(() => {
|
|
|
|
|
showNotification(them);
|
|
|
|
|
});
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
setTimeout(onClick, 100);
|
|
|
|
|
});
|
|
|
|
|
return <Child onClick={onClick} />
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
errors: [useEffectEventError('onClick', false)],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Invalid because functions created with useEffectEvent cannot be called in arbitrary closures.
|
|
|
|
|
@@ -1676,6 +1983,43 @@ const allTests = {
|
|
|
|
|
`It cannot be assigned to a variable or passed down.`,
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
syntax: 'flow',
|
|
|
|
|
code: normalizeIndent`
|
|
|
|
|
// Hook syntax version
|
|
|
|
|
// Invalid because functions created with useEffectEvent cannot be called in arbitrary closures.
|
|
|
|
|
hook useMyHook(theme: any) {
|
|
|
|
|
const onClick = useEffectEvent(() => {
|
|
|
|
|
showNotification(theme);
|
|
|
|
|
});
|
|
|
|
|
// error message 1
|
|
|
|
|
const onClick2 = () => { onClick() };
|
|
|
|
|
// error message 2
|
|
|
|
|
const onClick3 = useCallback(() => onClick(), []);
|
|
|
|
|
// error message 3
|
|
|
|
|
const onClick4 = onClick;
|
|
|
|
|
return <>
|
|
|
|
|
{/** error message 4 */}
|
|
|
|
|
<Child onClick={onClick}></Child>
|
|
|
|
|
<Child onClick={onClick2}></Child>
|
|
|
|
|
<Child onClick={onClick3}></Child>
|
|
|
|
|
</>;
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
// Explicitly test error messages here for various cases
|
|
|
|
|
errors: [
|
|
|
|
|
`\`onClick\` is a function created with React Hook "useEffectEvent", and can only be called from ` +
|
|
|
|
|
'Effects and Effect Events in the same component.',
|
|
|
|
|
`\`onClick\` is a function created with React Hook "useEffectEvent", and can only be called from ` +
|
|
|
|
|
'Effects and Effect Events in the same component.',
|
|
|
|
|
`\`onClick\` is a function created with React Hook "useEffectEvent", and can only be called from ` +
|
|
|
|
|
`Effects and Effect Events in the same component. ` +
|
|
|
|
|
`It cannot be assigned to a variable or passed down.`,
|
|
|
|
|
`\`onClick\` is a function created with React Hook "useEffectEvent", and can only be called from ` +
|
|
|
|
|
`Effects and Effect Events in the same component. ` +
|
|
|
|
|
`It cannot be assigned to a variable or passed down.`,
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|