【问题标题】:How can I resolver " useHref() may be used only in the context of a <Router> component" when component is already inside <Router>?当组件已经在 <Router> 中时,如何解析“useHref() 只能在 <Router> 组件的上下文中使用”?
【发布时间】:2021-12-24 13:41:52
【问题描述】:

我目前正在为我的 react 应用编写 Jest 测试。

当我为&lt;Container /&gt; 运行测试时,错误消息显示:

" useHref() 只能在组件的上下文中使用。"

但是,&lt;Container /&gt; 已经在 &lt;Router/&gt; 内部。

我在这里阅读了其他类似的问题,答案都说将组件放在&lt;Router/&gt;中,这就是我所做的。

Container.test.js

import { render, unmountComponentAtNode } from 'react-dom';
import Container from '../components/Container.tsx';
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
import { configure, shallow, mount } from 'enzyme';
import { Provider, useDispatch } from 'react-redux';
import { act } from "react-dom/test-utils";
import configureStore from 'redux-mock-store';

configure({adapter: new Adapter()});

const initState = { allCard: [], expansions: [] };
const mockStore = configureStore();
const wrapper = mount(<Provider store={mockStore(initState)}><Container/></Provider>);

describe('Container', () => {

    let container = null;
    beforeEach(() => {
    // setup a DOM element as a render target
    container = document.createElement("div");
    document.body.appendChild(container);
    });

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

    it('renders itself and its children without crashing', () => {
        render(<Provider store={mockStore(initState)}><Container /></Provider>, container);
    });

    it('renders itself without crashing', () => {
        const tree = wrapper.render();
        expect(tree.toJSON).toMatchSnapshot();
        });
});

App.js

import './App.css';
import Container from './components/Container';
import About from './components/RouteComponents/About';
import NavBar from './components/NavBar';
import Tutorials from './components/RouteComponents/Tutorials';
import Suggest from './components/RouteComponents/Suggest';
import Report from './components/RouteComponents/Report';
import { Route, Routes, BrowserRouter as Router } from 'react-router-dom';
import GlobalStyles from './components/styled/Globals.styled';
import { useState, createContext } from 'react';

function App() {
  const [ darkMode, setDarkMode ] = useState(false);

  return (
    <Router> 
      {darkMode? <GlobalStyles/> : null}
        <div className="App">
          <NavBar darkMode={darkMode} setDarkMode={setDarkMode}/>
          <Routes>
            <Route path='/' element= {<UserContext.Provider value={darkMode}>
                                          <Container />
                                      </UserContext.Provider>} />
            <Route path='/about' element={<About />} />
            <Route path='/tutorial' element= {<Tutorials />} />
            <Route path='/suggest' element={<Suggest />} />
            <Route path='/report' element= {<Report />} />
          </Routes>
        </div>
    </Router>
  );
}
export const UserContext = createContext(null);
export default App;

容器.tsx

import { useEffect, ReactElement } from 'react';
import axios from 'axios';
import { Link } from 'react-router-dom';
import { useDispatch } from 'react-redux'
import ErrorBoundary from './ErrorBoundary';
import ExpansionView from './ExpansionView';
import DisplayView from './DisplayView';
import SearchCard from './SearchCard';
import MurlocTidehunter from '../image/murlocTidehunter.png';
import SelectExpanionsMurloc from '../image/selectExpansions.png';
import { StyledContainer } from './styled/Container.styled';
import { eliminateMurloc } from '../utils/eliminateMurloc';

// Component - parent component that fetches allCard once when app launches
const Container = (): ReactElement => {
    const dispatch = useDispatch();
    
    useEffect(() => {
        const options: object = {
            method: 'GET',
            url: 'https://omgvamp-hearthstone-v1.p.rapidapi.com/cards',
            params: {collectible: '1'},
            headers: {
            'x-rapidapi-host': 'omgvamp-hearthstone-v1.p.rapidapi.com',
            'x-rapidapi-key': 'xxxxxxxxxx'
            }
        };
       
        // function to fetch all collectible cards from hearthstone api
        const fetchAllCards = async (): Promise<any> => {
            try {
                const response = await axios.request(options); 
                dispatch({type: 'SET_ALL_CARD', payload: response.data})
            } catch(e) {
                console.log(e)
            }
        }
        fetchAllCards();
    }, []);

    return (
        <StyledContainer>
            <h1 id='hearthfin'>Hearthfin</h1>
            <img id='tideHunter' className='deletableMurloc' src={MurlocTidehunter} alt="Hearthstone Murloc Analisis Videojuegos Zehngames - Murloc@seekpng.com" />
            <img id='selectExpMurloc' className='deletableMurloc' onClick={() => eliminateMurloc('selectExpMurloc')} src={SelectExpanionsMurloc} alt="Murloc that say select expansions first!" />
            <ErrorBoundary>
                <ExpansionView /> 
            </ErrorBoundary>
            <ErrorBoundary>
                <DisplayView />
            </ErrorBoundary>
            <p id='missingCard'>See a missing AOE card? Make a suggestion <Link to='suggest'>here!</Link></p>
            <ErrorBoundary>
                <SearchCard />
            </ErrorBoundary>
            <br/>
           
        </StyledContainer>
    );
}

export default Container;

【问题讨论】:

    标签: javascript reactjs jestjs react-router


    【解决方案1】:

    您在路由上下文之外渲染导航栏。路由器不知道链接试图链接它正在管理的路由。直接导航到“/”时路由起作用的原因是因为路由器在应用挂载时知道 URL

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    【解决方案2】:

    在您的“Container.tsx”文件中,像这样包装组件:

    import { BrowserRouter as Router } from 'react-router-dom';
    
    <Router> 
     <StyledContainer>
        //jsx elements
     </StyledContainer>
    <Router> 
    

    现在 Container 组件的“Link”不会混淆,因为 Link 会发现 Router 作为其组件的包装器。

    不要忘记从“app.js”文件中删除。其余的和以前一样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-29
      • 1970-01-01
      • 2021-04-02
      • 2021-01-31
      相关资源
      最近更新 更多