-
Notifications
You must be signed in to change notification settings - Fork 47.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[eslint-plugin-react-hooks] invariants, conditional calls and exhaustive deps #14942
Comments
const useTheme = listenToTheme
? () => React.useContext(ThemeContext)
: () => noopTheme
const noopTheme = {}
return function useStyles() {
const theme = useTheme()
// ...
} |
That looks likes a good pattern for hook factories, thanks. Maybe something worth adding to the docs if hook factories are common enough? |
I'm not sure it's better than: function makeStyles(stylesObjectOrCreator) {
const listenToTheme = typeof stylesObjectOrCreator === "function";
const noopTheme = {};
return function useStyles() {
// eslint-disable-next-line react-hooks/*
const theme = listenToTheme ? React.useContext(ThemeContext) : noopTheme; |
@oliviertassinari What makes the previous pattern better is that you're not able to use variables in the condition that are declared in the To check that we're not calling the hook factory in the component we can use the approach you suggested: function makeStyles(styles) {
if (process.env.NODE_ENV !== "production") {
let isInsideComponent = true;
try {
React.useState();
} catch (err) {
isInsideComponent = false;
}
if (isInsideComponent) {
console.warn(
`it appears youre calling makeStyles('${styles}') inside a component`
);
}
}
return function useStyles() {
const [state, setState] = React.useState();
return state;
};
} |
I think this is a bug report, but maybe there is a reason why it's not? useEffect(
() => {
props.loadCalendar(
governmentId,
{
endDate: currentRange[1].toISOString(),
startDate: currentRange[0].toISOString(),
}
);
},
[currentRange, governmentId, props.loadCalendar]
); This gives the error/warning:
If I destructure const {
loadCalendar,
} = props;
useEffect(
() => {
loadCalendar(
governmentId,
{
endDate: currentRange[1].toISOString(),
startDate: currentRange[0].toISOString(),
}
);
},
[currentRange, governmentId, loadCalendar]
); AFAIK, |
@MatthewHerbst The reason the rule suggests See here for additional context: #14920 (comment) |
@MatthewHerbst did you mean to post this in #14920? |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution. |
Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you! |
Do you want to request a feature or report a bug?
Not sure. Either feature to allow invariant conditional calls to hooks or bug in exhaustive deps in which case #14920 might be more appropriate.
What is the current behavior?
Linter reports that
React.useContext
is called conditionally but not thatlistenToTheme
is missing in the dependency list.If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have dependencies other than React. Paste the link to your JSFiddle (https://jsfiddle.net/Luktwrdm/) or CodeSandbox (https://codesandbox.io/s/new) example below:
https://codesandbox.io/s/o91zl0z499
What is the expected behavior?
It would expect one of these things:
rules-of-hooks
recognizes thatlistenToTheme
is invariant in the hook. Invariant conditions do not triggercalled conditionally
.exhaustive-deps
reports thatlistenToTheme
is missingIt's IMO more dangerous to add an
eslint-disable-next-line
to invariant conditional calls because it might be missed if someone changes the condition so that it no longer is invariant.It only occurs to me now that you don't consider it invariant because one might use it in the following way:
Still doesn't explain the missing
exhaustive-deps
warning.Are you open to a rule exception via configuration like
allow-invariant-conditionals
? Users would need to add additional rules so that hook factories are not called inside components.Ok talking to myself now: Even if everything stays the same and I remove the conditional call then users can still break their app by calling hook factories inside components:
The text was updated successfully, but these errors were encountered: