react-router:从组件或商店更改路由

时间:2017-07-19 14:27:10

标签: reactjs react-router reactjs-flux

我正在使用React,Flux和react-router(v4)捆绑。 我的目标是实现服务器端验证,并根据验证结果重定向到另一个路由或保持当前和显示验证消息。

我的想法遵循这种情况:

1)组件收集数据并调用操作

2)商店获得数据是否有效,保持结果并发出变化的响应

3)组件检测到变化并收集状态。如果验证成功,则重定向到新路由

组件中的功能部分看起来像(用TS编写):

public componentWillUpdate(): void {
    if (this.state.status === ValidationStatus.OK) {
        this.context.router.history.push(/* another route */);
    }
}

public render(): JSX.Element {
    return (
        <div>
            <div className='form-group'>
                <input type='text' ref='Field1' />
                <input type='text' ref='Field2' />
            </div>
            <span onClick={ (e) => this.tryToValidate(e) }>Go</span>
        </div>
    );
}

public componentDidMount(): void {
    this.onChange = this._onChange.bind(this);
    MyStore.addChangeListener(this.onChange);
}

private _onChange() {
    this.setState({
        status: MyStore.getStatus()
    });
}

但它无法正常工作 - 仅在第二次点击时才会触发重定向。

如何更改代码才能使其正常工作?可能是从商店或其他东西调用重定向?...

P.S。路由器的历史记录以这种方式包含在组件中:

public static contextTypes = {
    router: PropTypes.shape({
        history: PropTypes.shape({
            createHref: PropTypes.func.isRequired,
            push: PropTypes.func.isRequired,
            replace: PropTypes.func.isRequired
        }).isRequired
    }).isRequired
}

更新

找到一个有效的解决方案,但看起来很难看:

  • 从组件回调传递到存储作为有效负载(回调引发context.router.history.push(/* another route */);

  • 如果服务器验证正常,则在商店中执行此回调。

1 个答案:

答案 0 :(得分:0)

最后我发现了解决方案。只需要将历史记录包含在内(例如草稿,而不是工作代码):

import * as history from 'history'

class MyDataStore {

    private dataService = new ValidationService();

    constructor() {
        super();
        AppDispatcher.getInstance().register((payload) => {
            let action = payload.action;
            switch (action.actionType) {
                case AppActions.VALIDATE:
                    this.dataService.validate(action.data).then((validationOk) => {
                        if (validationOk) {
                            history.createHashHistory().push(/* another route */);
                        } else {
                            this.emitChange(); // stay on current route
                        }
                    });

                    break;
                default:
                    return true;
            }

            this.emitChange();
        });
    }

}

唯一的缺点是它只使用HashRouter而不是BrowserRouter。我不知道原因,试图找出......