Разработка React Hooks предотвращает реагирование на хуки / исчерпывающие предупреждения
Я разрабатываю ловушку для получения данных только при изменении зависимостей хуков. Он работает, как ожидалось, но я получаю предупреждения линтера:
React Hook useEffect was passed a dependency list that is not an array literal. This means we can't statically verify whether you've passed the correct dependencies.
а также
React Hook useEffect has missing dependencies: 'data', 'errorHandler', 'route', and 'successHandler'. Either include them or remove the dependency array. If 'successHandler' changes too often, find the parent component that defines it and wrap that definition in useCallback.
Насколько мне известно, мне не нужны все эти переменные в моих зависимостях, поскольку я не хочу запускать этот хук, когда они меняются, я хочу активировать его только тогда, когда меняются передаваемые мной зависимости.
Вопрос: как я могу спроектироватьuseFetch()
перехватить так, чтобы он соответствовал стандартам перехватчиков линтера (если мой шаблон проектирования не соответствует номиналу, пожалуйста, поясните, как лучше всего этого добиться).
Мой useFetch()
крюк
function useFetch(
{
route,
data = {},
successHandler,
errorHandler,
},
dependencies = []) {
const [loading, setLoading] = useState(true);
useEffect(() => {
setLoading(true);
postJson({route}, data)
.then(
res => {
if(isFunction(successHandler)) successHandler(res);
},
({responseJSON: err}) => {
if(isFunction(errorHandler)) {
errorHandler(err);
} else {
notify({text: err.message || messages.saveFailed(), cssClass: 'error'});
}
}
)
.finally(() => {
setLoading(false);
});
}, dependencies);
return loading;
}
Компонент с использованием useFetch()
function MyComponent({data, selectedReviewId, setField}) {
const loading = useFetch({
route: 'foo.fetchData',
data: {crrType, clientId, programId, userId},
successHandler: d => setField([], d) // setField() will set data with the value fetched in useFetch()
}, [selectedReviewId]);
return loading ? <SpinnerComponent/> : <div>{data.foo}</div>;
}
2 ответа
Вы передали зависимость как массив, но на принимающей стороне это, по сути, единственная переменная, указывающая на массив. Lint правилоuseEffect()
требует, чтобы вы указывали зависимости в квадратных скобках, как в следующем коде.
Теперь немного технических деталей. Помните, что вызывает предупреждение. Это линт, который проверяет код синтаксически. В семантику это не входит. Семантически ваш список зависимостей верен, поскольку вы передаете массив, но синтаксически он не передается как массив, то есть это единственная переменная, не переданная в квадратных скобках (например,[dependencies]
) (который ищет линт). Итак, чтобы удовлетворить lint, вы должны написать:
useEffect(
() => { // implementation of function },
[dependencies]
);
Кроме того, поскольку вы отправляете массив зависимостей, вы также можете использовать оператор распространения, например:
useEffect(
() => { // implementation of function },
[...dependencies]
);
Это распространит элементы массива внутри оператора массива с помощью транспилятора Babel. Линт также останется тихим.
В eslint
предупреждение верно - вы должны включить их как зависимости. Например, в вашемMyComponent
если data
изменений, и его нет в вашем списке зависимостей, ваш useEffect
хук будет вызывать извлечение будет устаревшим data
.
То же самое относится и к другим - рекомендуется добавить их в список зависимостей.
Для первой ошибки это, вероятно, нормально, хотя и не идеально. У вас есть динамический список зависимостей -eslint
не могу быть уверен, есть ли у вас там все необходимое.
Ваше решение, вероятно, сработает, но оно очень хрупкое. Если твойdependencies
могут измениться (например, дополнительные элементы или удаленные элементы)