【问题标题】:React router changes url but not viewReact路由器更改url但不查看
【发布时间】:2018-07-25 21:08:50
【问题描述】:

我无法更改视图以响应路由。我只想显示用户列表,单击每个用户应该导航到详细信息页面。这是路由器:

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from 'react-router-dom';
import Users from "./components/Users";
import { Router, Route } from "react-router";
import Details from "./components/Details";

ReactDOM.render((
  <BrowserRouter>
    <div>
        <Route path="/" component={Users} />
        <Route path="/details" component={Details} />
    </div>
  </BrowserRouter>
), document.getElementById('app'))

当我使用 url /details 时,我的浏览器会导航到该 url,但不会更改视图。任何其他路线都会抛出 404,因此它似乎可以识别路线但不会更新。

【问题讨论】:

  • 我收到两个错误:一个声明不推荐使用主反应包中的 proptypes。不推荐使用两个使用 React.createClass 的声明。我认为这无关紧要,因为代码可以在不使用路由的情况下工作。
  • 您的组件安装正确吗?

标签: reactjs react-router


【解决方案1】:

您需要为您的 indexRoute 指定属性 exact,否则即使是 /details 路由它仍然会与 / 匹配。也尝试从react-router-dom导入Route

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Route } from 'react-router-dom';
import Users from "./components/Users";

import Details from "./components/Details";

ReactDOM.render((
  <BrowserRouter>
    <div>
        <Route exact path="/" component={Users} />
        <Route path="/details" component={Details} />
    </div>
  </BrowserRouter>
), document.getElementById('app'))

更新:

您需要做的另一件事是将组件用户附加到withRouter。只有当你的组件没有收到Router props时,你才需要使用withRouter

这可能发生在以下情况下:您的组件是 Router 渲染的组件的嵌套子组件,或者您没有将 Router 属性传递给它,或者当组件根本没有链接到路由器,而是作为独立于路由的组件呈现。

在 Users.js 中添加

import {withRouter} from 'react-router';

.........
export default withRouter(Users)

DOCS

【讨论】:

  • proptypes 警告可以通过安装 npm install -S 'prop-types' 并将 React.PropsTypes 替换为 PropTypes 来删除。还要更新你的 package.json 以使用最新的打包,因为其他包可能仍在使用 React.PropTypes 和 React.createClass
  • 另外你是否尝试在 url 更改时重新加载页面以查看是否加载
  • 我确实尝试重新加载页面,它不会改变视图。即使 url 是 /#/details,它也会加载到用户视图中
  • 你能用从'react-router-dom`导入的Route而不是react-router来尝试更新的答案
  • 如果还没有解决,请将你的用户组件绑定到withRouter,它已经帮助我解决了同样的问题。让我知道。我也更新了代码。
【解决方案2】:

您只需将组件包装在 withRouter 中。

<Route exact path="/mypath" component={withRouter(MyComponent)} />

这是一个示例 App.js 文件:

...
import { BrowserRouter as Router, Route, Switch, withRouter } from "react-router-dom";
import Home from "./pages/Home";
import Profile from "./pages/Profile";

class App extends Component {
  render() {
    return (
      <Router>
        <Switch>
          <Route exact path="/" component={withRouter(Home)} />
          <Route exact path="/profile" component={withRouter(Profile)} />
        </Switch>
      </Router>
    );
  }
}

export default App;

附加

如果你使用 react 路由,componentWillReceiveProps 会在 url 改变时被调用。

componentWillReceiveProps(nextProps) {
    var currentProductId = nextProps.match.params.productId;
    var nextProductId = nextProps.match.params.productId; // from the new url
    ...
}

注意

或者,您也可以在导出之前将组件包装在 withRouter 中,但是您必须确保其他一些事情。我通常跳过这一步。

export default withRouter(Profile)

【讨论】:

  • 为我工作
【解决方案3】:

我遇到了同样的问题,发现这是因为我有一个嵌套路由器。一旦我删除了嵌套路由器,并将我的特定于组件的路由简单地放在一个交换机组件中,问题就得到了解决,而无需使用 withRouter 或进行任何其他更改。

<Router> // <--Remove nested Router
    <Switch>
      <Route exact path="/workflows" component={ViewWorkflows} />
      <Route path="/workflows/new" component={NewWorkflow} />
    </Switch>
</Router>

Yusufbek 正在描述一个类似的问题。我认为将与组件相关的路由存储在视图级别比将所有路由存储在一个主路由器中要干净得多。在生产应用程序中,要轻松阅读和调试问题的路径太多了。

【讨论】:

  • 我正在使用 create-react-app 这对我有用。当然,我按照一些 youtube 教程构建了我的路由器设置,因此 create-react-app 可能不相关。
【解决方案4】:

我遇到了同样的问题,但我已经解决了。我把主页放在最后。这个对我有用。就像下面一样。

    import React from "react";
    import ReactDOM from "react-dom";
    import { BrowserRouter } from 'react-router-dom';
    import Users from "./components/Users";
    import { Router, Route } from "react-router";
    import Details from "./components/Details";

    ReactDOM.render((
      <BrowserRouter>
        <div>
            <Route path="/details" component={Details} />
            <Route path="/" component={Users} />
        </div>
      </BrowserRouter>
    ), document.getElementById('app'))

【讨论】:

  • 使用exact 属性也可以为您解决这个问题。
【解决方案5】:

我遇到了类似的问题,但结构不同。我添加了一个可以处理所有路由的路由器,我使用了 Switch 组件来切换视图。但实际上,并没有。仅更改了 URL,但未更改视图。原因是 SideBar 组件内部使用的 Link 组件位于 Router 组件之外。 (是的,我已经用“withRouter”导出了 SideBar,但没有用)。 因此,解决方案是将包含所有 Link 组件的 SideBar 组件移动到我的路由器中。

问题出在我的链接器中,它们在我的路由器之外

<div className="_wrapper">
  <SideBar /> // Holds my all linkers
  <Router>
     <Switch>
       <Route path="/" component={Home} />
       <Route path="/users" component={Users} />
     </Switch>
  </Router>
 </div>

解决方案是将我的链接器移动到我的路由器中

<div className="_wrapper">
  <Router>
     <SideBar /> // Holds my all linkers
     <Switch>
       <Route path="/" component={Home} />
       <Route path="/users" component={Users} />
     </Switch>
  </Router>
</div>

【讨论】:

  • 帮助自己成就了我的一天。我正在尝试使用两个独立的路由器。一个在导航栏中,一个在正文中以容纳组件。现在,我将所有内容都放在父组件的同一个路由器中,一切正常。
  • 优秀 - 我的确切问题。谢谢
  • 谢谢!你救了我!!
  • 我已经尝试了所有方法,包括 withRouter,但只有这个解决方案确实有效......解释一下将有助于理解为什么会发生这种情况
  • @Jim 我认为 react-router 使用上下文 API,&lt;Router /&gt; 又名 &lt;BrowserRouter /&gt;&lt;Route /&gt;&lt;Switch /&gt; 等路由匹配器和 &lt;Link /&gt; 等导航组件提供上下文, &lt;Redirect /&gt;。为了提供相同的上下文,您必须将所有子组件包装在上下文提供程序中,即&lt;Router /&gt;
【解决方案6】:

react-router-dom 5 也有同样的问题

问题是由history 包引起的。 我使用的版本是5.0.0,但它们不能一起使用。

通过将history 降级为4.10.1 修复

相关问题:https://github.com/ReactTraining/history/issues/804

【讨论】:

    【解决方案7】:

    BrowserRouter 在您的情况下无法维护历史记录。改用“路由器”,将其与自定义历史记录一起用作道具可能有助于解决您的问题。

    import {Router, Route, Switch, withRouter } from "react-router-dom";
    import Home from "./pages/Home";
    import Profile from "./pages/Profile";
    import {createBrowserHistory} from 'history';
    
    export const customHistory = createBrowserHistory();  //This maintains custom history
    
    class App extends Component {
      render() {
        return (
          <Router history={customHistory}>
            <Switch>
              <Route exact path="/" component={Home} />
              <Route exact path="/profile" component={Profile} />
            </Switch>
          </Router>
        );
      }
    }
    
    export default App;
    

    然后在您的组件中,从“App”导入 customHistory 并使用它进行导航。

    customHistory.push('/pathname');
    

    希望这有帮助! :)

    【讨论】:

    • 使用Switch时不需要exact属性
    【解决方案8】:

    在使用 Redux 时,我遇到了类似的问题,即地址栏中的 url 正在更新,但应用程序没有加载相应的组件。我能够通过将 withRouter 添加到导出来解决:

    import { connect } from 'react-redux'
    import { withRouter } from 'react-router-dom'
    
    export default withRouter(connect(mapStateToProps)(MyComponentName))
    

    【讨论】:

    • 但是,它适用于功能组件吗?
    【解决方案9】:

    就我而言,我错误地嵌套了两个BrowserRouters。

    【讨论】:

      【解决方案10】:

      您需要将精确添加到索引路由,而不是通过 div 封闭那些 Route 组件,而是使用 react-router-dom 中的 Switch 在路由之间切换。

      import React from "react";
      import ReactDOM from "react-dom";
      import { Route, Switch } from 'react-router-dom';
      import Users from "./components/Users";
      
      import Details from "./components/Details";
      
      ReactDOM.render((
        <div>
          <Switch>
              <Route path="/" component={Users} exact/>
              <Route path="/details" component={Details} />
          </Switch>
        </div>
      ), document.getElementById('app'))
      

      【讨论】:

        【解决方案11】:

        我尝试在主路径前添加“精确” 像这样

        &lt;Route exact path="/" component={Home}&gt;&lt;/Route&gt;

        一切正常……

        【讨论】:

        • 就像,真的把 exact 移到 to 前面,而不是在帮助之后。想要我的调试时间回来
        【解决方案12】:

        我在使用 React Router 版本 4 时遇到了类似的问题:

        点击&lt;Link /&gt;组件,URL会改变,但视图不会改变。

        其中一个观点是使用PureComponent 而不是Component(从react 导入),这就是原因。

        通过将所有使用PureComponent 的路由渲染组件替换为Component,我的问题得到解决。

        (解析来源:https://github.com/ReactTraining/react-router/issues/4975#issuecomment-355393785

        【讨论】:

        • 谢谢。那为我修好了。但它只是包含 Switch 的组件,我必须从 Component 而不是 PureComponent 扩展,以便实时视图更改工作。
        • 我已将纯组件更改为组件,但它对我不起作用。
        【解决方案13】:

        嗯,没有任何 SWITCH 可以实际切换视图。

        这就是我使用路由器从登陆页面切换到主站点的方式

        //index.jsx    
        ReactDOM.render( (<BrowserRouter><App/></BrowserRouter>), document.getElementById('root') );
        
        
        //App.jsx
        render()
        {
            return <div>
                <Switch>
                    <Route exact path='/' component={Lander}/>
                    <Route path='/vadatajs' component={Vadatajs}/>
                </Switch>
            </div>
        }
        

        https://jsfiddle.net/Martins_Abilevs/4jko7arp/11/

        我发现你使用不同的路由器..对不起,也许这个小提琴对你有用

        https://fiddle.jshell.net/terda12/mana88Lm/

        也许解决方案的关键是隐藏在主渲染功能的行中..

        Router.run(routes, function(Handler) {
            React.render(<Handler />, document.getElementById('container'));
        });
        

        【讨论】:

          【解决方案14】:

          我遇到了类似的问题,我决定喜欢这个,请看看我希望它有效。

          您需要在组件中使用 componentWillReceiveProps 函数。

          第一次通过调用 url 点击链接 www.example.com/content1/ componentDidMount() 运行。

          现在,当您单击另一个链接时说 www.example.com/content2/ 调用了相同的组件,但这次 prop 发生了变化,您可以在 componentWillReceiveProps(nextProps) 下访问这个新的 prop,您可以使用它来调用 API 或将状态设为空白并获取新数据。

          componentWillReceiveProps(nextProps){
               //call your API and update state with new props
          }
          

          【讨论】:

            【解决方案15】:

            对我来说,我有:

            export MyClass extends React.Component
            

            与:

            export default withRouter(MyClass)
            

            同时,在我的 App.js 中,我有:

            import { MyClass } from './MyClass'
            

            那些玩主场比赛的人可以看到我的问题。我没有将路由器导入子类中。为了清理它,我将 withRouter 调用移到了 Route 组件声明中:

            <Router exact path={'/myclass'} component={withRouter(MyClass)} />
            

            回到 MyClass,我将其更改为默认导出:

            export default MyClass extends React.Component
            

            最后,在 App.js 中,我将导入更改为:

            import MyClass from './MyClass'
            

            希望这对某人有所帮助。这确保我没有两种方法来导出同一个类,从而绕过 withRouter 前置。

            【讨论】:

              【解决方案16】:

              我也遇到了同样的问题。虽然不是很有效的解决办法,但我还是用狡猾的方法解决了。 每次我们的 url 更改时,ComponentDidMount 方法都会起作用。 在该方法中,我们可以将之前的 url 与当前的 url 进行比较,我们可以改变状态或刷新页面。

              componentDidUpdate(prevProps) {
                  if (this.props.match.url !== prevProps.match.url) {
                      //this.props.history.go(0) refresh Page
                      //this.setState(...) or change state
                  }
              }
              

              【讨论】:

                【解决方案17】:
                <Route exact path="/" component={Users} />
                <Route exact path="/details" component={Details} />
                

                我也遇到了同样的问题,使用 exact 属性解决了这个问题。尝试使用exact 属性。

                【讨论】:

                  【解决方案18】:

                  我也遇到了麻烦。

                  https://github.com/chengjianhua/templated-operating-system

                  我已经尝试了 Shubham Khatri 提出的解决方案,但它不起作用。


                  我解决了这个问题,也许可以帮到你。

                  https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/blocked-updates.md

                  根据上述指南文档,当您使用PureComponent或与reduxmobx等状态管理工具一起使用时,可能会阻止您的路线更新。检查你的路由组件,确保你没有阻止你的组件的重新渲染。

                  【讨论】:

                    【解决方案19】:

                    你应该看看这个:https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/blocked-updates.md

                    因此肯定不是UsersDetails,因为它们是由&lt;Route&gt;直接渲染的,而location会被传递给props

                    我在想,为什么你需要&lt;BrowserRouter&gt;&lt;Route&gt; 之间的&lt;div&gt;?删除它,让我知道它是否有效。

                    【讨论】:

                      【解决方案20】:

                      我在条件布局方面遇到了类似的问题:

                      class LayoutSwitcher extends Component {
                        render () {
                          const isLoggedIn = this.props.isLoggedIn
                          return (
                            <React.Fragment>
                              { isLoggedIn
                                ? <MainLayout {...this.props} />
                                : <Login />
                              }
                            </React.Fragment>
                          )
                        }
                      }
                      

                      并像这样重写条件:

                        render () {
                          const isLoggedIn = this.props.isLoggedIn
                          if (isLoggedIn) {
                            return <MainLayout {...this.props} />
                          }
                          return <Login />
                        }
                      

                      这解决了它。就我而言,上下文似乎丢失了。

                      【讨论】:

                        【解决方案21】:

                        我遇到了同样的问题。 我不认为在这种情况下他需要添加带有Router的道具, 只需检查您的 NavLink,您就可以将好的路径名作为详细信息写入。 对于路线尝试从特定路线开始到一般路线

                        <Route path="/details" component={Details} />
                        <Route path="/" component={Users} />
                        

                        在您的 NavLink 中应该是这样的

                         <NavLink className="nav-link" to="/details">
                           details<span className="sr-only">(current)</span>
                         </NavLink>
                        

                        对于导入来说最好先导入与 React 相关的所有内容,然后再导入另一个模块 喜欢这个:

                        import React from "react";
                        import ReactDOM from "react-dom";
                        import { BrowserRouter } from 'react-router-dom';
                        import Users from "./components/Users";
                        import { Router, Route } from "react-router";
                        import Details from "./components/Details";
                        

                        像这样来:

                        import React from "react";
                        import ReactDOM from "react-dom";
                        import { BrowserRouter } from 'react-router-dom';
                        import { Router, Route } from "react-router";
                        
                        import Users from "./components/Users";    
                        import Details from "./components/Details";
                        

                        【讨论】:

                          【解决方案22】:

                          就我而言,切换到 HashRouter 而不是 BrowserRouter 解决了我的问题

                          【讨论】:

                            【解决方案23】:

                            我不小心在我的链接周围使用了 BrowserRouter。

                            <BrowserRouter>
                                <div>
                                    <Link to="/" component={Users} />
                                    <Link to="/details" component={Details} />
                                </div>
                            </BrowserRouter>
                            

                            【讨论】:

                              【解决方案24】:

                              如果您最近才开始遇到此问题,请查看 https://github.com/remix-run/react-router/issues/7415

                              问题在于 react-router-dom 5+ 和历史依赖项。

                              如果您使用yarn install history单独安装它,则需要卸载它,请使用yarn install history@4.10.1

                              【讨论】:

                                【解决方案25】:

                                试试这个,

                                import React from "react";
                                
                                import ReactDOM from "react-dom";
                                import Users from "./components/Users";
                                import { Router, Route } from "react-router";
                                
                                
                                import Details from "./components/Details";
                                
                                ReactDOM.render((
                                  <Router>
                                        <Route path="/" component={Wrapper} >
                                            <IndexRoute component={Users} />
                                            <Route path="/details" component={Details} />
                                        </Route>
                                  </Router>
                                ), document.getElementById('app'))
                                

                                【讨论】:

                                • 定义一个将呈现 this.props.children 的 Wrapper 组件。这将正确路由。
                                【解决方案26】:

                                我遇到了同样的问题,我修复了它从 node_modules 中的 @types 文件夹导入历史记录。我从 npm (npm i @history) 导入它

                                【讨论】:

                                  【解决方案27】:

                                  我建议您检查用户和详细信息组件。它们不应该有路由器组件。如果您在它们内部使用&lt;Link to=../&gt;,它位于&lt;Router&gt; 内部,请尝试删除路由器并仅使用链接。

                                  【讨论】:

                                    【解决方案28】:

                                    如果有人使用history 包进行导航并且您使用的是react-router v5,那么您可能必须将history 包降级为4.10.1,直到history 包开发人员发布新版本与修复。在撰写本文时,history 软件包的最新版本是v5.0.1,如果您看到比这更新的版本,您可以先尝试使用该版本,看看它是否有效,然后再降级到4.10.1

                                    问题链接->https://github.com/remix-run/history/issues/804

                                    【讨论】:

                                      【解决方案29】:

                                      如果你像上面的例子那样配置路由器组件,并尝试从任何组件访问 history.push 或 props.history.push,你可能会遇到在更改 URL 时不渲染组件的问题。您可以通过直接从 react-router-dom 导入路由器来解决此问题,而不是将 BrowserRouter 作为路由器导入。您可以在下面找到更正后的代码。

                                      例如:导入{ 路由器, 转变, 路线, } 来自“react-router-dom”;

                                      不是: 进口 { BrowserRouter 作为路由器, 转变, 路线, } 来自“react-router-dom”;

                                      【讨论】:

                                        【解决方案30】:

                                        刚刚遇到这个老问题。

                                        引用的代码中缺少 OP 的 &lt;Switch&gt; 块。那肯定会阻止事情正常工作。

                                        【讨论】:

                                        猜你喜欢
                                        • 2018-08-02
                                        • 1970-01-01
                                        • 2020-04-07
                                        • 1970-01-01
                                        • 2022-08-24
                                        • 1970-01-01
                                        • 2022-01-10
                                        • 2020-04-17
                                        相关资源
                                        最近更新 更多