Flux / Fluxible:根据状态变化更新路径

时间:2015-04-16 15:18:34

标签: javascript reactjs reactjs-flux react-router

使用Fluxible和react路由器,根据对状态存储的更改来触发路由更改的最简洁方法是什么?

示例组件可能需要一些用户输入并在单击事件上调用Action(为简洁起见缩短)

class NameInput extends React.Component {

    constructor (props) {
        super(props);
        this.state = props.state;
        this.handleClick = this.handleClick.bind(this);
    }

    handleClick (event) {
        this.context.executeAction(setName, {name:'Some User Value'});
    }

    render () {
        return (
            <div>
                <input type="button" value="Set Name" onClick={this.handleClick} />
            </div>
        );
    }
}

export default Home;

handleClick方法执行一个Action,它可以使用我们的新值更新Store。

但是如果我希望在更新商店后触发导航怎么办?我可以添加router上下文类型,并在执行Action后直接调用transition方法:

this.context.executeAction(setName, {name:'Some User Value'});
this.context.router.transitionTo('some-route');

但这假设setName动作是同步的。这在概念上是否安全,假设一旦Action完成并且Store更新后新路由将​​重新呈现?

或者,如果原始组件侦听商店更改并根据对商店状态的某些评估启动路由转换?

使用Fluxible,connectToStores实现,我可以倾听对Store状态的谨慎更改:

NameInput = connectToStores(NameInput, [SomeStore], function (stores, props) {
    return {
        name: stores.SomeStore.getState().name
    }
});

如何使用此类型的Store侦听器来启动路由更改?

2 个答案:

答案 0 :(得分:2)

我在自己的应用程序中注意到,对于这些类型的流程,让行动完成所有艰苦工作通常会更安全。这里令人讨厌的是路由器无法通过操作访问。

所以,这就是我要做的事情:

创建同时执行这两项操作的元操作:setNameAndNavigate。作为有效载荷,您可以使用以下内容:

{
   name: 'Value',
   destination: {to: 'some-route', params: []},
   router: this.context.router
}

然后,在您的操作中,在setName完成时进行导航。

这并不理想,特别是将路由器传递给动作。可能有一些方法将路由器连接到动作上下文,但这并不像我希望的那么简单。这可能是一个很好的起点。


额外阅读:

为什么一切都在行动?在响应商店更改时在组件中执行操作是有风险的。由于Fluxible 0.4,你不能再让行动在内部发送另一个派遣。这种情况发生的速度比您想象的要快得多,例如,执行操作以响应商店中的更改而不用setImmediatesetTimeout延迟执行操作,将会导致应用程序停止,因为存储更改会同步发生发货。

但是,在内部操作中,您可以轻松执行操作和调度,并等待它们在执行下一个操作之前完成。

以这种方式工作的最终结果是,您的大多数应用程序逻辑已转移到操作,并且您的组件变成了简单的视图,即为了响应用户交互而设置并忽略的操作(单击/滚动/悬停/ ...,只要它不响应商店更改)。

答案 1 :(得分:2)

最好的方法是创建@ambroos建议的新动作, setNameAndNavigate。但是要进行导航,请使用navigateAction https://github.com/yahoo/fluxible/blob/master/packages/fluxible-router/lib/navigateAction.js,你只需要将url作为参数。 像这样的东西,

import async from 'async';
import setName from 'some/path/setName'; 

export default function setNameAndNavigate(context, params, done) {
   async.waterfall([
      callback => {
          setName(context, params, callback);
      },
      (callback) => {
          navigate(context, {
             url: '/someNewUrl',
          }, callback);
       }
   ], done);    
}

尽可能让你的行动成为主要工作者。