【问题标题】:react-router-dom `history`: Cannot read property 'push' of undefinedreact-router-dom `history`:无法读取未定义的属性“推送”
【发布时间】:2021-09-20 21:11:41
【问题描述】:

我的父组件中有App.js 一个Header 和一个Footer。
我想通过单击它们两个内部的按钮在Header 和Footer 之间切换组件。
每次pageIndex 更改时,我都想替换为其他组件。

我收到此错误Cannot read property 'push' of undefined
为什么我会收到此错误并且是干净且适当的乳清(使用我的defaultRouter() 和useMemo)?

 function App() {
      const [pageIndex, setPageIndex] = useState();
      const [searchResults, setSearchResults] = useState([]);

      const history = useHistory();

       useEffect(() => {
         console.log(pageIndex, 'App');
       }, [pageIndex]);
    
    const defaultRouter = useMemo(() => {
     // Or -  `const DefaultRouter = useMemo(() =>` instead of `useEffect()`
    switch (pageIndex) {
      case 1:
        history.push({ pathname: '/search', state: searchResults });
        break;
      case 2:
        history.push('/cart');
        break;
      default:
        history.push('/');
        break;
    }
   }, [pageIndex]);

      return (
        <div className='App'>
          <Header/>
          <Home />
          {defaultRouter};  
          <Footer />  
          <BrowserRouter>
            <Route path='/'>
              <Home />
            </Route>
            <Route path='/search'>
              <Search
                searchResults={searchResults}
                setItemsAmount={setItemsAmount}
              />
            </Route>
            <Route path='/cart'>
              <Cart />
            </Route>
            <Route component={PageNotFound} />
          </BrowserRouter>
          ;
        </div>
      );
    }

编辑

正如 Shyam 在下面的回答中建议的那样,我将 App.js 更改为 useCallback 但 useCallback 不起作用。

  const defaultRouter = useCallback(() => {
    console.log(pageIndex, 'callBack');
    switch (pageIndex) {
      case 1:
        history.push({ pathname: '/search', state: searchResults });
        break;
      case 2:
        history.push('/cart');
        break;
      default:
        history.push('/');
        break;
    }
  }, [pageIndex]);

谢谢

【问题讨论】:

    标签: reactjs routes react-router react-router-dom browser-history


    【解决方案1】:

    这是因为该组件中没有设置 react-router 上下文。 由于它是设置上下文的组件,因此您可以在子组件中使用 useHistory,但不能在该子组件中使用。

    这是解决这个问题的一个非常基本的策略:

    const AppWrapper = () => {
      return (
        <Router> // Set context
          <App /> // Now App has access to context
        </Router>
      )
    }
    
    const App = () => {
      let history = useHistory(); // Works!
    ...
    

    // 在这个组件中渲染路由 然后确保直接使用“包装器”组件而不是 App。

    在这里回答: https://stackoverflow.com/a/58221867/1723410

    function App() {
      return (
        <BrowserRouter>
           <AppChildren />
        </BrowserRouter>
      )
    }     
    
    function AppChildren() {
          const [pageIndex, setPageIndex] = useState();
          const [searchResults, setSearchResults] = useState([]);
    
          const history = useHistory();
    
           useEffect(() => {
             console.log(pageIndex, 'App');
           }, [pageIndex]);
        
        const defaultRouter = useMemo(() => {
         // Or -  `const DefaultRouter = useMemo(() =>` instead of `useEffect()`
        switch (pageIndex) {
          case 1:
            history.push({ pathname: '/search', state: searchResults });
            break;
          case 2:
            history.push('/cart');
            break;
          default:
            history.push('/');
            break;
        }
       }, [pageIndex]);
    
          return (
            <div className='App'>
              <Header/>
              <Home />
              {defaultRouter};  
              <Footer />  
              <>
                <Route path='/'>
                  <Home />
                </Route>
                <Route path='/search'>
                  <Search
                    searchResults={searchResults}
                    setItemsAmount={setItemsAmount}
                  />
                </Route>
                <Route path='/cart'>
                  <Cart />
                </Route>
                <Route component={PageNotFound} />
              </>
            </div>
          );
    } 
    

    【讨论】:

    • 1) AppWrapper 是否应该在不同的 jsx 文件中并被导出? 2) 我现在的useCallback 在Header 组件中更新pageIndex 时不起作用。
    • 我试过了,就是不行,useCallback,useMemo或者useEffect也不行
    • 如何/在哪里使用 AppWrapper ?我尝试使用 index.js 而不是 &lt;App/&gt; 但它给出了错误 - TypeError: Cannot read property 'location' of undefined
    • 所以你的 BrowserRouter 必须在父组件中。我更新了上面的答案
    猜你喜欢
    • 2018-10-19
    • 2018-10-24
    • 2021-11-24
    • 1970-01-01
    • 2016-01-31
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多