mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 12:20:20 +01:00
144 lines
3.5 KiB
JavaScript
144 lines
3.5 KiB
JavaScript
/**
|
|
* Exhaustive Deps
|
|
*/
|
|
// Valid because dependencies are declared correctly
|
|
function Comment({comment, commentSource}) {
|
|
const currentUserID = comment.viewer.id;
|
|
const environment = RelayEnvironment.forUser(currentUserID);
|
|
const commentID = nullthrows(comment.id);
|
|
useEffect(() => {
|
|
const subscription = SubscriptionCounter.subscribeOnce(
|
|
`StoreSubscription_${commentID}`,
|
|
() =>
|
|
StoreSubscription.subscribe(
|
|
environment,
|
|
{
|
|
comment_id: commentID,
|
|
},
|
|
currentUserID,
|
|
commentSource
|
|
)
|
|
);
|
|
return () => subscription.dispose();
|
|
}, [commentID, commentSource, currentUserID, environment]);
|
|
}
|
|
|
|
// Valid because no dependencies
|
|
function UseEffectWithNoDependencies() {
|
|
const local = {};
|
|
useEffect(() => {
|
|
console.log(local);
|
|
});
|
|
}
|
|
function UseEffectWithEmptyDependencies() {
|
|
useEffect(() => {
|
|
const local = {};
|
|
console.log(local);
|
|
}, []);
|
|
}
|
|
|
|
// OK because `props` wasn't defined.
|
|
function ComponentWithNoPropsDefined() {
|
|
useEffect(() => {
|
|
console.log(props.foo);
|
|
}, []);
|
|
}
|
|
|
|
// Valid because props are declared as a dependency
|
|
function ComponentWithPropsDeclaredAsDep({foo}) {
|
|
useEffect(() => {
|
|
console.log(foo.length);
|
|
console.log(foo.slice(0));
|
|
}, [foo]);
|
|
}
|
|
|
|
// Valid because individual props are declared as dependencies
|
|
function ComponentWithIndividualPropsDeclaredAsDeps(props) {
|
|
useEffect(() => {
|
|
console.log(props.foo);
|
|
console.log(props.bar);
|
|
}, [props.bar, props.foo]);
|
|
}
|
|
|
|
// Invalid because neither props or props.foo are declared as dependencies
|
|
function ComponentWithoutDeclaringPropAsDep(props) {
|
|
useEffect(() => {
|
|
console.log(props.foo);
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, []);
|
|
useCallback(() => {
|
|
console.log(props.foo);
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, []);
|
|
useMemo(() => {
|
|
console.log(props.foo);
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, []);
|
|
React.useEffect(() => {
|
|
console.log(props.foo);
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, []);
|
|
React.useCallback(() => {
|
|
console.log(props.foo);
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, []);
|
|
React.useMemo(() => {
|
|
console.log(props.foo);
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, []);
|
|
React.notReactiveHook(() => {
|
|
console.log(props.foo);
|
|
}, []); // This one isn't a violation
|
|
}
|
|
|
|
/**
|
|
* Rules of Hooks
|
|
*/
|
|
// Valid because functions can call functions.
|
|
function normalFunctionWithConditionalFunction() {
|
|
if (cond) {
|
|
doSomething();
|
|
}
|
|
}
|
|
|
|
// Valid because hooks can call hooks.
|
|
function useHook() {
|
|
useState();
|
|
}
|
|
const whatever = function useHook() {
|
|
useState();
|
|
};
|
|
const useHook1 = () => {
|
|
useState();
|
|
};
|
|
let useHook2 = () => useState();
|
|
useHook2 = () => {
|
|
useState();
|
|
};
|
|
|
|
// Invalid because hooks can't be called in conditionals.
|
|
function ComponentWithConditionalHook() {
|
|
if (cond) {
|
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
useConditionalHook();
|
|
}
|
|
}
|
|
|
|
// Invalid because hooks can't be called in loops.
|
|
function useHookInLoops() {
|
|
while (a) {
|
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
useHook1();
|
|
if (b) return;
|
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
useHook2();
|
|
}
|
|
while (c) {
|
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
useHook3();
|
|
if (d) return;
|
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
useHook4();
|
|
}
|
|
}
|