Jest.js useNavigate() may be used only in the context of a < Router> component

zazmityj  于 2022-12-08  发布在  Jest
关注(0)|答案(6)|浏览(428)

看我下面的代码。我试图添加这个按钮,使用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>
  );
}

这是我在控制台中遇到的错误:

yzuktlbb

yzuktlbb1#

此错误会掷回useNavigate。useInRouterContext会检查元件(使用useNavigate拦截)是否为<Router>的子代。
下面的源代码解释了为什么不能在Router组件之外使用useNavigateuseLocation
useNavigate在底层使用useLocationuseLocation将从LocationContext提供器获取位置。如果要获取响应上下文,则应将组件呈现为上下文提供器的后代。Router组件使用LocationContext.Provider和NavigationContext.Provider。这就是为什么需要将组件呈现为子级的原因。以便useNavigate挂钩可以从NavigationContextLocationContext提供程序获取上下文数据。
您的环境是浏览器,因此需要使用BrowserRouterBrowserRouter是基于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')
)
vd2z7a6w

vd2z7a6w2#

我在测试一个有钩子useNavigate的组件时遇到了同样的问题。通过用RoutesBrowserRouter将我的组件 Package 在一个Route中解决了这个问题。希望这能帮助其他有同样错误的人。

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'))
});
ohfgkhjo

ohfgkhjo3#

您使用的是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>
  );
}
1dkrff03

1dkrff034#

供日后参考:从react-router-dom导入<Router>,从react-router导入useNavigate时,也可能出现此错误;

uubf1zoe

uubf1zoe5#

问题

我的错误是

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> Package 呈现的元素来解决这个错误:

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

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

dm7nw8vv6#

使用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>

相关问题