React Router v4 从 MobX 存储操作导航?

React Router v4 Navigate from MobX store action?

我试图让 React router v4 从 store 中的一个动作导航,而不是明确地将 history 道具传递给每个在某些逻辑运行后需要导航的存储动作。

我正在寻找类似这样的东西来工作:

import { NavigationStore } from 'navigation-store';

class ContactStore {
  @action contactForm(name, message){
    // Some logic runs here

    // Then navigate back or success

    // Go back
    NavigationStore.goBack();

    // Or Navigate to Route
    NavigationStore.push('/success'); 
  }
}

当然 NavigationStore 不存在(我不知道从 React Router 中放入什么才能使其工作),但我希望导入一个我可以使用的 mobx 导航存储使用与 react-router

相同的 api 导航到应用程序(组件或商店)中的任何位置

怎么做?

更新:

RR4 没有给我们提供从商店的操作导航的方法。我正在尝试使用 RR4 导航 就像上面 一样。我只需要知道 navigation-store 应该包含什么,这样我就可以:

  1. import { NavigationStore } from 'navigation-store'; 任何地方 (component/store),也具有历史意识,能够从任何地方导航。
  2. NavigationStore.RR4Method(RR4MethodParam?); 其中 RR4Method 是可用的 RR4 导航选项,如推送、返回等。(这就是导航应该发生的方式)

更新二:

因此 url 现在从 NavigationStore.push('/success'); 更新,但没有网页刷新。

这里是navigation-store.js

import { observable, action } from 'mobx'
import autobind from 'autobind-decorator'
import createBrowserHistory from 'history/createBrowserHistory'

class NavigationStore {
  @observable location = null;
  history = createBrowserHistory();

  @autobind push(location) {
    this.history.push(location);
  }
  @autobind replace(location) {
    this.history.replace(location);
  }
  @autobind go(n) {
    this.history.go(n);
  }
  @autobind goBack() {
    this.history.goBack();
  }
  @autobind goForward() {
    this.history.goForward();
  }
}

const navigationStore = new NavigationStore();

export default navigationStore;

这里是app.js

import React from 'react'
import { Provider } from 'mobx-react'
import { BrowserRouter as Router, Route } from 'react-router-dom'
import Contact from 'screens/Contact'
import Success from 'screens/Success'

export default class App extends React.Component {
  render() {
    return (
      <div>
        <Provider>
          <Router>
            <div>
              <Route path='/contact' component={Contact} />
              <Route path='/success' component={Success} />
            </div>
          </Router>
        </Provider>
      </div>
    );
  }
}

一旦 url 更改为 /success,在这种情况下网页不会发生任何变化,而是加载匹配的组件 Success。还是卡在这里..

更新3(解决方案):

我把它放在这里作为其他人的参考,因为它让我很沮丧。

app.js中我不得不改变:

import { BrowserRouter as Router, Route } from 'react-router-dom'
<Router>

import { Route } from 'react-router-dom'
import { Router } from 'react-router'
import navigationStore from 'stores/navigation-store'
<Router history={navigationStore.history}>

我希望这对其他人有帮助:)

您始终可以将商店用作另一个商店的构造函数参数。然后您将能够正确使用 NavigationStore 实例。

因此,在您初始化商店的地方,您可以拥有:

const navigationStore = new NavigationStore(); 
const contactStore = new ContactStore(navigationStore)
const stores = {
    navigationStore, 
    contactStore
}

然后您的联系人存储变成:

class ContactStore {
  _navigationStore; 
  constructor(navigationStore) {
    this._navigationStore = navigationStore;
  }
  @action contactForm(name, message){
    // Some logic runs here

    // Then navigate back or success

    // Go back
    this._navigationStore.goBack();

    // Or Navigate to Route
    this._navigationStore.push('/success'); 
  }
}

编辑

您也可以use a singleton导出商店的实例,然后通过在任何模块中导入它来使用它。所以你可以有这样的东西:

navigationStore.js

class NavigationStore() {
    goBack() {...}; 
    push(target) {...};
}
const navigationStore = new NavigationStore();
// The trick here is to export the instance of the class, not the class itself
// So, all other modules use the same instance.  
export default navigationStore;

contactStore.js

import navigationStore from 'navigation-store';
// We import the naviationStore instance here

class ContactStore {
  @action contactForm(name, message){
    // Some logic runs here

    // Then navigate back or success

    // Go back
    navigationStore.goBack();

    // Or Navigate to Route
    navigationStore.push('/success'); 
  }
}

App.js:为 mobx 提供商初始化商店的位置:

import navigationStore from './navigationStore'; 
// We import the same instance here, to still have it in the provider.
// Not necessary if you don't want to inject it. 

const stores = {
    navigationStore, 
    contactStore: new ContactStore();
}