在 BrowserRouter 中使用 MemoryRouter

Mr_*_*een 6 reactjs react-router

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

/one --> BrowserRouter (url change visible)
    /
    /first
    /second
    /third
/two --> BrowserRouter (url change visible)
    /
    /first
    /second
    /third
Run Code Online (Sandbox Code Playgroud)

对于新的可见路由,即/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>
Run Code Online (Sandbox Code Playgroud)

然后是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>
Run Code Online (Sandbox Code Playgroud)

我正在努力实现的目标:

  • 使屏幕与 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'));
Run Code Online (Sandbox Code Playgroud)

zhu*_*ber 7

起初我认为与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>
Run Code Online (Sandbox Code Playgroud)

如果您有更多的嵌套路由总是添加精确到根,请小心,例如/first需要精确以使其正常工作:

<Route exact path="/first" component={FirstPage}></Route>
<Route path="/first/nested-1" component={SecondPage}></Route>
<Route path="/first/nested-2" component={ThirdPage}></Route>
Run Code Online (Sandbox Code Playgroud)