Переместить константу / функцию в пользовательский хук / повторно используемый фрагмент кода

#reactjs #typescript #ionic-framework #react-hooks

#reactjs #typescript #ионный фреймворк #реагирующие хуки

Вопрос:

В моем функциональном компоненте / странице у меня есть const / function, которому я передаю сообщения об ошибках, который затем обновляет пару записей useState и регистрирует ошибку на консоли. Это выглядит так:

 const catchError = (e:any, message:string) => {
    //throw new Error(e)
    setMessage(message);
    setLoading(false);
    console.error(e);
};
 

Я хотел бы переместить этот код в хук (?) / вспомогательный файл, который позволит мне импортировать его в любой другой компонент. Это означало бы, что я могу использовать один централизованный фрагмент кода, а не писать один и тот же код в нескольких местах и избегать связанных с этим проблем.

Итак, я создал новый catchError.tsx файл со следующим содержимым:

 import { useState } from 'react';

const [ message, setMessage ] = useState("idle");
const [ loading, setLoading ] = useState(false);

export const catchError = (e:any, message:string) => {
    //throw new Error(e)
    setMessage(message);
    setLoading(false);
    console.error(e);
};
 

Однако, когда я визуализирую это, я получаю следующую ошибку компиляции:

Не удалось скомпилировать

Строка src / hooks / catchError.tsx 3:33: Реагирующий хук «useState» не может быть вызван на верхнем уровне. Реагирующие хукеры должны вызываться в компоненте функции React или пользовательской функции React-hooks / rules-of-hooks Строка 4:33: Реагирующий хук «useState» не может быть вызван на верхнем уровне. Реагирующие хукеры должны вызываться в компоненте функции React или пользовательской функции React-Hook react-hooks / rules-of-hooks

Найдите ключевые слова, чтобы узнать больше о каждой ошибке.

Для меня это новая территория.

(PS: я новичок в React / TypeScript и буду приветствовать любые исправления в моей терминологии).

Комментарии:

1. имя файла catchError.tsx и имя функции должны иметь префикс use like this useCatchError , чтобы react распознал его как пользовательский хук. Кроме того, вы должны переместить свои пользовательские состояния внутри функции

Ответ №1:

Если вы хотите повторно использовать логику хуков (например, useState), вы можете написать свои собственные пользовательские хуки.

Я считаю, что что-то вроде so может сработать, хотя я не совсем уверен, как это будет использоваться без дополнительного контекста.

 import { useState } from 'react';

function useCatchError() {
  const [ message, setMessage ] = useState("idle");
  const [ loading, setLoading ] = useState(false);

  const catchError = (e:any, message:string) => {
    //throw new Error(e)
    setMessage(message);
    setLoading(false);
    console.error(e);
  };

  return { catchError, message, loading };
}
 

И использоваться как

 export function Foo() {
  const {catchError, message, loading} = useCatchError();
  
  try {
    bar();
  } catch (e) {
    catchError(e, e.message);
  }

  return (
    <div>
       {message ? `Error: ${message}` : loading ? "Loading" : "Foo"}
    </div>
  );
}
 

Подробнее о пользовательских хуках в документах React: https://reactjs.org/docs/hooks-custom.html

Комментарии:

1. Спасибо. Я не хочу ничего возвращать, мне просто нужно передать 2 значения (e и message). Затем используйте catchError с любой другой страницы / компонента, импортировав его. Если я импортирую useCatchError в соответствии с вашим кодом и импортирую при import { catchError } from '../hooks/useCatchError'; получении ошибки Module '"../hooks/useCatchError"' has no exported member 'catchError'. , какие-либо предложения?

2. P.s. Мой код catchError буквально соответствует тому, что я опубликовал в своем вопросе. Мне просто нужно иметь возможность повторно использовать этот код на нескольких компонентах / страницах без ручного добавления этого кода полностью на каждую страницу. Спасибо.

3. Если вы не хотите возвращать сообщение и значение загрузки, которое вы можете заменить, return { catchError, message, loading }; return catchError и тогда вы сможете получить эту функцию const catchError = useCatchError(); . Однако вам нужно вызывать хук в вашем методе рендеринга для каждого компонента, обойти это невозможно.