source

useNavigate()는 컴포넌트의 컨텍스트에서만 사용할 수 있습니다.

gigabyte 2023. 3. 15. 19:40
반응형

useNavigate()는 컴포넌트의 컨텍스트에서만 사용할 수 있습니다.

아래 코드를 참조하십시오.이 버튼을 추가하여 이전 페이지로 돌아가려고 합니다.react-router-dom하지만 아래 오류가 발생하고 웹 사이트의 모든 컴포넌트가 사라집니다.

오류:

useNavigate() may be used only in the context of a component

내 코드:

function App() {
  const navigate = useNavigate();
  return (
    <BrowserRouter>
      <div>
      <button onClick={() => navigate(-1)}>go back</button>
        <Nav/>
        <Routes>
          <Route exact path="/" element={<Home/>}/>
          <Route exact path="/home" element={<Home/>}/>
          <Route exact path="/upcoming/:user" element={<Upcoming/>}/>
          <Route exact path="/record/:user" element={<Record/>}/>
          <Route path="*" element={<NotFound/>}/>
        </Routes>
      </div>
    </BrowserRouter>
  );
}

콘솔에 표시되는 오류는 다음과 같습니다.

에러

이 오류는 useNavigate를 발생시킵니다.useInRouterContext는 컴포넌트(가useNavigate훅)은 의 후손입니다.<Router>.

여기 왜 사용할 수 없는지를 설명하는 소스 코드입니다.useNavigate,useLocation을 벗어나서Router컴포넌트:

useNavigate사용하다useLocation밑바닥에useLocation는 Location Context 공급자에서 위치를 가져옵니다.반응 컨텍스트를 가져오려면 구성 요소를 컨텍스트 공급자의 하위 항목으로 렌더링해야 합니다. Router컴포넌트는 Location Context를 사용합니다.프로바이더Navigation Context.프로바이더그렇기 때문에 컴포넌트를 자식으로 렌더링해야 합니다.useNavigate후크는 컨텍스트 데이터를 가져올 수 있습니다.NavigationContext그리고.LocationContext프로바이더

고객님의 환경은 브라우저이므로BrowserRouter.BrowserRouter을 기반으로 구축되어 있습니다.Router.

이에 대한 리팩터:

App.jsx:

function App() {
  const navigate = useNavigate();
  return (
      <div>
        <button onClick={() => navigate(-1)}>go back</button>
        <Nav/>
        <Routes>
          <Route exact path="/" element={<Home/>}/>
          <Route exact path="/home" element={<Home/>}/>
          <Route exact path="/upcoming/:user" element={<Upcoming/>}/>
          <Route exact path="/record/:user" element={<Record/>}/>
          <Route path="*" element={<NotFound/>}/>
        </Routes>
      </div>
  );
}

index.jsx:

import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './App';

ReactDOM.render(
  <BrowserRouter>
    <App/>
  </BrowserRouter>,
  document.getElementById('root')
)

같은 문제가 있었지만 후크가 있는 컴포넌트를 테스트하는 경우useNavigate내 컴포넌트를 포장에 싸서 해결했어Route와 함께Routes그리고.BrowserRouter같은 에러를 안고 있는 다른 사람에게도 도움이 되었으면 합니다.

let container = null;
    beforeEach(() => {
    container = document.createElement("div");
    document.body.appendChild(container);
});

afterEach(() => {
    // cleanup on exiting
    unmountComponentAtNode(container);
    container.remove();
    container = null;
});

test('finds qualified insurrance policies', () => {
    act(() => {
    render(
    <BrowserRouter>
        <Routes>   
            <Route path="*" element= {<QuaifiedPolicies policyTypes={false} />}/>
        </Routes>
    </BrowserRouter>
        , container);
    });
    expect(screen.getByLabelText('some text'))
});

밖에서 후크를 사용하고 있습니다.BrowserRouter프로바이더그래서 에러가 나는 거예요.이 문제를 해결하려면 컴포넌트를 다음과 같이 리팩터링하십시오.

function Root() {
  const navigate = useNavigate();
  return (
    <div>
      <button onClick={() => navigate(-1)}>go back</button>
      <Nav />
      <Routes>
        <Route exact path="/" element={<Home />} />
        <Route exact path="/home" element={<Home />} />
        <Route exact path="/upcoming/:user" element={<Upcoming />} />
        <Route exact path="/record/:user" element={<Record />} />
        <Route path="*" element={<NotFound />} />
      </Routes>
    </div>
  );
}

function App() {
  return (
    <BrowserRouter>
      <Root />
    </BrowserRouter>
  );
}

향후 참조를 위해:이 에러는, 유저에 의한 Import에서도 발생할 수 있습니다.<Router>부터react-router-dom및 ImportuseNavigate부터react-router.

문제

저의 정확한 실수는

console.error
      Error: Uncaught [Error: useNavigate() may be used only in the context of a <Router> component.]

이 문제가 발생한 것은 다음 유닛테스트 코드를 실행하고 있는 경우뿐입니다.

// Act
const button: HTMLElement = render(<MyButton myChoice="myChoice" />).container;

// Assert
expect(button).toHaveTextContent("myChoice");

솔루션

렌더링된 요소를 로 감싸서 오류를 해결했습니다.<BrowserRouter>:

// Act
const button: HTMLElement = render(
    <BrowserRouter>
        <MPBenefitChoiceButton selectedChoice={selectedChoice} />
    </BrowserRouter>
).container;

// Assert
expect(button).toHaveTextContent(buttonText);

사용하는 컴포넌트useNavigate이 끝나야 한다<Router> ... </Router>

예.

<Router>
      <AuthProvider>    <----- useNavigate used in this component 
        <NavBar />
        <Routes>
          <Route exact path="/login" element={<LoginForm />} />
          <Route exact path="/register" element={<RegisterForm />} />
        </Routes>
      </AuthProvider>
</Router>
<OtherComponent/>  <----- if useNavigate use inside this component then  
                         error occur because useNavaigate work inside  
                         <Router> Component so it should wrap inside <Router>

다음과 같이 합니다.

<Router>
      <AuthProvider>    
        <NavBar />
        <Routes>
          <Route exact path="/login" element={<LoginForm />} />
          <Route exact path="/register" element={<RegisterForm />} />
        </Routes>
      </AuthProvider>
      <OtherComponent/>
</Router>
  

언급URL : https://stackoverflow.com/questions/70491774/usenavigate-may-be-used-only-in-the-context-of-a-router-component

반응형