我正在使用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 */);
)
如果服务器验证正常,则在商店中执行此回调。
答案 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。我不知道原因,试图找出......