Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1755,6 +1755,40 @@ const tests = {
},
],
},
{
code: normalizeIndent`
function MyComponent({foo, one}) {
useEffect(() => {
console.log(one);
if (foo?.bar) {
console.log(foo.bar);
}
}, [one]);
}
`,
errors: [
{
message:
"React Hook useEffect has a missing dependency: 'foo?.bar'. " +
'Either include it or remove the dependency array.',
suggestions: [
{
desc: 'Update the dependencies array to be: [foo?.bar, one]',
output: normalizeIndent`
function MyComponent({foo, one}) {
useEffect(() => {
console.log(one);
if (foo?.bar) {
console.log(foo.bar);
}
}, [foo?.bar, one]);
}
`,
},
],
},
],
},
{
code: normalizeIndent`
function MyComponent() {
Expand Down Expand Up @@ -8191,19 +8225,19 @@ const testsTypescript = {
errors: [
{
message:
"React Hook useEffect has a missing dependency: 'pizza.crust'. " +
"React Hook useEffect has a missing dependency: 'pizza?.crust'. " +
'Either include it or remove the dependency array.',
suggestions: [
{
desc: 'Update the dependencies array to be: [pizza.crust]',
desc: 'Update the dependencies array to be: [pizza?.crust]',
output: normalizeIndent`
function MyComponent() {
const pizza = {};

useEffect(() => ({
crust: pizza?.crust,
density: pizza.crust.density,
}), [pizza.crust]);
}), [pizza?.crust]);
}
`,
},
Expand All @@ -8225,19 +8259,19 @@ const testsTypescript = {
errors: [
{
message:
"React Hook useEffect has a missing dependency: 'pizza.crust'. " +
"React Hook useEffect has a missing dependency: 'pizza?.crust'. " +
'Either include it or remove the dependency array.',
suggestions: [
{
desc: 'Update the dependencies array to be: [pizza.crust]',
desc: 'Update the dependencies array to be: [pizza?.crust]',
output: normalizeIndent`
function MyComponent() {
const pizza = {};

useEffect(() => ({
crust: pizza.crust,
density: pizza?.crust.density,
}), [pizza.crust]);
}), [pizza?.crust]);
}
`,
},
Expand Down
12 changes: 5 additions & 7 deletions packages/eslint-plugin-react-hooks/src/rules/ExhaustiveDeps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1905,13 +1905,11 @@ function markNode(
): void {
if (optionalChains) {
if ('optional' in node && node.optional) {
// We only want to consider it optional if *all* usages were optional.
if (!optionalChains.has(result)) {
// Mark as (maybe) optional. If there's a required usage, this will be overridden.
optionalChains.set(result, true);
}
} else {
// Mark as required.
// Prefer optional chaining if any usage needs it, because dependency
// arrays are evaluated outside guarded blocks.
optionalChains.set(result, true);
} else if (!optionalChains.has(result)) {
// Mark as required unless an optional usage has already been seen.
optionalChains.set(result, false);
}
}
Expand Down