reactjs - 在 BrowserRouter 中使用 MemoryRouter

标签 reactjs react-router

在我的项目中,我必须在不更改 url 的情况下从一个组件导航到另一个组件。为此,我使用了 MemoryRouter这按预期工作。但现在同样的想法应该适用于不同的路线,即 /one/two .例如,

/one --> BrowserRouter (url change visible)
    /
    /first
    /second
    /third
/two --> BrowserRouter (url change visible)
    /
    /first
    /second
    /third

对于新的可见路由,即 /one/two ,已经建立的工作内存路由(即 //first/second/third )应该按照 /one 中提供的相应数据正常工作和 /two .

我正在努力使用以下结构代码将 MemoryRoutes 包含在 BrowserRoutes 中:
    <BrowserRouter>
      <Switch>
        <Route path="/one" render={() => <MemoryComp configFor="Dave"></MemoryComp>}></Route>
        <Route path="/two" render={() => <MemoryComp configFor="Mike"></MemoryComp>}></Route>
      </Switch>
    </BrowserRouter>

然后是 MemoryComp持有:
  <MemoryRouter history={customHistory}>
    <Switch>
      <Route path="/" render={(props) => <InitPage configFor={this.props.configFor} history={props.history}></InitPage>}></Route>
      <Route path="/first" component={FirstPage}></Route>
      <Route path="/second" component={SecondPage}></Route>
      <Route path="/third" component={ThirdPage}></Route>
    </Switch>
  </MemoryRouter>

我正在努力实现的目标:
  • 使屏幕与 BrowserRouter --> MemoryRouter 配置一起工作。
  • 根据主浏览器路由将数据从内存路由传递到另一个内存路由。 (尝试使用 history 来实现相同的效果)

  • 笔记:
    这更有可能更好地用服务器路由来处理浏览器路由内容。此外,这似乎可以通过任何 react-stepper 插件来实现。但试图了解我在这里做错了什么,只是为了学习目的。

    这是完整的最小化代码,可在 Stackblitz 上找到(不工作):
    import React, { Component } from 'react';
    import { render } from 'react-dom';
    import './style.css';
    import { BrowserRouter, MemoryRouter, Route, Switch } from 'react-router-dom';
    import { createBrowserHistory } from "history";
    
    const customHistory = createBrowserHistory();
    
    class MemoryComp extends Component{
      render(){
        return(
          <MemoryRouter history={customHistory}>
            <Switch>
              <Route path="/" render={(props) => <InitPage configFor={this.props.configFor} history={props.history}></InitPage>}></Route>
              <Route path="/first" component={FirstPage}></Route>
              <Route path="/second" component={SecondPage}></Route>
              <Route path="/third" component={ThirdPage}></Route>
            </Switch>
          </MemoryRouter>
        );
      }
    }
    
    class InitPage extends Component{
      render(){
        return (
          <>
            <ul>
              <li onClick={() => this.navigateTo("/")}>Init</li>
              <li onClick={() => this.navigateTo("/first")}>First</li>
              <li onClick={() => this.navigateTo("/second")}>Second</li>
              <li onClick={() => this.navigateTo("/third")}>Third</li>
            </ul>
            <div>{this.props.configFor}</div>
          </>
        )
      }
    
      navigateTo(path){
        this.props.history.push(path, {
          data: {
            configFor: this.props.configFor
          }
        })
      }
    }
    
    class FirstPage extends Component{
      constructor(props){
        super(props);
        this.data = this.props.history.location.state.data;
      }
      render(){
        return (
          <>
            <ul>
              <li onClick={() => this.navigateTo("/")}>Init</li>
              <li onClick={() => this.navigateTo("/first")}>First</li>
              <li onClick={() => this.navigateTo("/second")}>Second</li>
              <li onClick={() => this.navigateTo("/third")}>Third</li>
            </ul>
            <div>first page</div>
          </>
        )
      }
    
      navigateTo(path){
        this.props.history.push(path, {
          data: {...this.data, ...{pageName: 'first'}}
        })
      }
    }
    
    class SecondPage extends Component{
      constructor(props){
        super(props);
        this.data = this.props.history.location.state.data;
      }
      render(){
        return (
          <>
            <ul>
              <li onClick={() => this.navigateTo("/")}>Init</li>
              <li onClick={() => this.navigateTo("/first")}>First</li>
              <li onClick={() => this.navigateTo("/second")}>Second</li>
              <li onClick={() => this.navigateTo("/third")}>Third</li>
            </ul>
            <div>second page</div>
          </>
        )
      }
    
      navigateTo(path){
        this.props.history.push(path, {
          data: {...this.data, ...{name: 'deducedValue'}}
        })
      }
    }
    
    class ThirdPage extends Component{
      constructor(props){
        super(props);
        this.data = this.props.history.location.state.data;
      }
      render(){
        return (
          <>
            <ul>
              <li onClick={() => this.navigateTo("/")}>Init</li>
              <li onClick={() => this.navigateTo("/first")}>First</li>
              <li onClick={() => this.navigateTo("/second")}>Second</li>
              <li onClick={() => this.navigateTo("/third")}>Third</li>
            </ul>
            <div>third page</div>
          </>
        )
      }
    
      navigateTo(path){
        this.props.history.push(path, {
          data: this.data
        })
      }
    }
    
    class App extends Component {
      constructor() {
        super();
        this.state = {
          name: 'React'
        };
      }
    
      render() {
        return (
          <div>
            <BrowserRouter>
              <Switch>
                <Route path="/one" render={() => <MemoryComp configFor="Dave"></MemoryComp>}></Route>
                <Route path="/two" render={() => <MemoryComp configFor="Mike"></MemoryComp>}></Route>
              </Switch>
            </BrowserRouter>
          </div>
        );
      }
    }
    
    render(<App />, document.getElementById('root'));
    

    最佳答案

    一开始我以为Switch有问题结合 MemoryRouter ,但经过一些调试后,我意识到它实际上是完全独立的。

    您遇到的问题是您的基本内存路由需要是 exact ,否则所有其他路由将匹配该路由,并且将返回第一个 ('/')。只需添加 exact到您的基本路线。

    <MemoryRouter>
        <Switch>
          <Route exact path="/" render={(props) => <InitPage configFor={this.props.configFor} history={props.history}></InitPage>}></Route>
          <Route path="/first" component={FirstPage}></Route>
          <Route path="/second" component={SecondPage}></Route>
          <Route path="/third" component={ThirdPage}></Route>
        </Switch>
      </MemoryRouter>
    

    如果您有更多的嵌套路由总是添加精确到根,请小心,例如/first需要准确才能使其正常工作:
    <Route exact path="/first" component={FirstPage}></Route>
    <Route path="/first/nested-1" component={SecondPage}></Route>
    <Route path="/first/nested-2" component={ThirdPage}></Route>
    

    关于reactjs - 在 BrowserRouter 中使用 MemoryRouter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60716732/

    相关文章:

    reactjs - 如何在我的 nextjs 应用程序中更新我的模板

    javascript - 如何使用 React-Router 的 NavLink 重新加载页面?

    javascript - React js 路由无法正常工作

    javascript - React中如何判断当前路由是否活跃

    javascript - React 访问index.html 中的组件

    reactjs - 如何自定义 React Native TextInput 的高度?

    css - 如何使用 classNames 和 JSX 在 reactjs 元素中使用 css 模块设置子项的样式

    javascript - 如何使用 javascript 以特定格式显示日期月份和年份并使用react?

    reactjs - React-Router 在新选项卡中打开链接

    javascript - 无法使用 Link 组件传递状态。为什么状态未定义?