no-useless-custom-hooks
Full Name in eslint-plugin-react-hooks-extra
react-hooks-extra/no-useless-custom-hooks
Full Name in @eslint-react/eslint-plugin
@eslint-react/hooks-extra/no-useless-custom-hooks
Features
🔍
Presets
recommended
recommended-typescript
recommended-type-checked
What it does
Enforces custom Hooks to use at least one other Hook inside.
If your function doesn’t call any Hooks, avoid the use
prefix. Instead, write it as a regular function without the use
prefix. For example, useSorted
below doesn’t call Hooks, so call it getSorted
instead:
// 🔴 Avoid: A Hook that doesn't use Hooks
function useSorted(items) {
return items.slice().sort();
}
// ✅ Good: A regular function that doesn't use Hooks
function getSorted(items) {
return items.slice().sort();
}
This ensures that your code can call this regular function anywhere, including conditions:
function List({ items, shouldSort }) {
let displayedItems = items;
if (shouldSort) {
// ✅ It's ok to call getSorted() conditionally because it's not a Hook
displayedItems = getSorted(items);
}
// ...
}
You should give use
prefix to a function (and thus make it a Hook) if it uses at least one Hook inside of it:
// ✅ Good: A Hook that uses other Hooks
function useAuth() {
return useContext(Auth);
}
Technically, this isn’t enforced by React. In principle, you could make a Hook that doesn’t call other Hooks. This is often confusing and limiting so it’s best to avoid that pattern. However, there may be rare cases where it is helpful. For example, maybe your function doesn’t use any Hooks right now, but you plan to add some Hook calls to it in the future. Then it makes sense to name it with the use
prefix:
// ✅ Good: A Hook that will likely use some other Hooks later
function useAuth() {
// TODO: Replace with this line when authentication is implemented:
// return useContext(Auth);
return TEST_USER;
}
Then components won’t be able to call it conditionally. This will become important when you actually add Hook calls inside. If you don’t plan to use Hooks inside it (now or later), don’t make it a Hook.
Examples
Failing
function useSorted(items) {
return items.slice().sort();
}
Passing
function getSorted(items) {
return items.slice().sort();
}
function useAuth() {
return useContext(Auth);
}
function useAuth() {
// TODO: Replace with this line when authentication is implemented:
// return useContext(Auth);
return TEST_USER;
}