react: использование хука из функции, вызываемой в компоненте, а не из самого компонента

Необходимо в React из функции (не компоненте, но функция вызывается из компонента) выполнить навигацию

Создал хук:

// хук для выполнения навигации
export const useCustomNavigate = () => {
    const navigate = useNavigate();
    return navigate;
  };

И использую внутри функции:

    // обработать 401 ошибка: не авторизованный запрос
    if (errMessage === 'Unauthorized') {
        // выйти из системы
        logout()

        // перейти на страницу авторизации
        const navigate = useCustomNavigate();

        navigate('/auth/login');
    }

и получаю ошибку:

React Hook "useCustomNavigate" is called in function "queryCustom" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use" react-hooks/rules-of-hooks

Подскажите как с этим бороться?

не хочется выполнять этот код в самом компоненте, в компоненте работать с useNavigate() хочется чтоб такая вещь (которая много где используется) выполнялась централизованно (код лежал бы в утилитах как отдельная функция) и желательно ничего бы не требовал от компонента на вход (если это возможно)

Подскажите как решить данную проблему?

P.S.

как временное решение (не знаю насколько оно правильное) я в main.tsx (по сути в главном компоненте) использовал

const navigate = useNavigate();

а navigate положил в синглтон и использую navigate по всему проекту


Ответы (1 шт):

Автор решения: ksa

Необходимо в React из функции (не компоненте, но функция вызывается из компонента) выполнить навигацию

Вот смотри... В примере есть хук и функция. Есть вариант привязки всего этого в компоненте. Есть и вызов функции. Т.е. вроде как все твое имеется.

Если в поле будет значение Unauthorized будет выполнен "переход" по твоему УРЛ.

// хук для выполнения навигации
const useCustomNavigate = () => {
  //const navigate = useNavigate();
  const [navigate, setNavigate] = React.useState('');
  return [navigate, setNavigate]
};

//
function test(navigate) {
  return function(errMessage) {
    // обработать 401 ошибка: не авторизованный запрос
    if (errMessage === 'Unauthorized') {
      // выйти из системы
      //logout()
      // перейти на страницу авторизации
      //const navigate = useCustomNavigate();
      navigate('/auth/login');
    }
  }
}
//
function App() {
  const [val, setVal] = React.useState('')
  const [navigate, setNavigate] = useCustomNavigate()
  const fnc = test(setNavigate)
  const act = e => {
    const v = e.target.value
    fnc(v)
    setVal(v)
  }
  return <section>
    <input type='text' onChange={act} value={val} />
    <p>{navigate}</p>
  </section>
}

const domContainer = document.querySelector('#like_button_container');
const root = ReactDOM.createRoot(domContainer);
root.render(<App />);
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<div id="like_button_container"></div>

→ Ссылка