根据React组件的状态来反应路由器

时间:2016-06-09 10:56:28

标签: reactjs react-router

我遇到了react-router的问题。

我的路线文件如下:

const routes = (
<Route path="/" component={App}>
    <IndexRoute component={HomePage}/>
    <Route path="registration" component={Registration}>
        <Route path="/registration-step-one" component={RegistrationStepOne} />
        <Route path="/registration-step-two" component={RegistrationStepTwo}/>
        <Route path="/registration-step-three" component={RegistrationStepThree}/>
        <Route path="/registration-step-four" component={RegistrationStepFour}/>
    </Route>
    <Route path="reset-password" component={PasswordReset} />
</Route>
);

我有一个重要的组件注册,它有四个步骤。然后单击提交按钮,状态发生变化,下一步显示。

注册组件代码是:

onButtonClick(name, event) {
    event.preventDefault();
    switch (name) {
        case "stepFourConfirmation":
            this.setState({step: 1});
            break;
        case "stepTwoNext":
            this.setState({step: 3, errors: {}});
            break;
        case "stepThreeFinish":
            this.setState({step: 4});
            break;
        default:
            this.setState({step: 2, errors: {}});
    }
}

render() {
    const languageReg = this.props.currentLanguage.default.registrationPage;

    let formStep = '';
    let step = this.state.step;
    switch (step) {
        case 1:
            formStep = (<RegistrationFormStepOne user={this.state.user}
                                                 onChange={this.setUser}
                                                 onButtonClick={this.onButtonClick}
                                                 onClick={this.changeStep}
                                                 errors={this.state.errors}/>);
            break;
        case 2:
            formStep = (<RegistrationFormStepTwo user={this.state.user}
                                                 onChange={this.setUser}
                                                 onButtonClick={this.onButtonClick}
                                                 onClick={this.changeStep}
                                                 errors={this.state.errors}/>);
            break;
        case 3:
            formStep = (<RegistrationFormStepThree user={this.state.user}
                                                   onFileChange={this.onFileChange}
                                                   onButtonClick={this.onButtonClick}
                                                   onClick={this.changeStep}
                                                   errors={this.state.errors}
                                                   files={this.state.files}
                                                   fileChosen={this.state.selectedFile}/>);
            break;

        default:
            formStep = (<RegistrationFormStepFour user={this.state.user}
                                                  onChange={this.setUser}

                                                  onChangeCheckboxState={this.changeCheckboxState}
                                                  emailNotificationsState={this.state.user.emailNotifications}
                                                  termsState={this.state.user.terms}
                                                  smsNotificationsState={this.state.user.smsNotifications}

                                                  onButtonClick={this.onButtonClick}
                                                  onClick={this.changeStep}
                                                  errors={this.state.errors}/>);
    }

    return (
        <div className="sidebar-menu-container" id="sidebar-menu-container">

            <div className="sidebar-menu-push">

                <div className="sidebar-menu-overlay"></div>

                <div className="sidebar-menu-inner">
                    <div className="contact-form">
                        <div className="container">
                            <div className="row">
                                <div className="col-md-10 col-md-offset-1 col-md-offset-right-1">
                                    {React.cloneElement(formStep, {currentLanguage: languageReg})}
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    );
}

但是,如果我在第三步,我在浏览器中单击,我将重定向到主页。有没有办法让路由器只进入上一步而不是主页?或者,如果我使用状态来更改表单步骤,则无法完成?

1 个答案:

答案 0 :(得分:1)

您可以使用routerWillLeave挂钩执行此操作。请在official react-router documentation上了解详情。

这是你能做的:

componentDidMount = () => {
  this.props.router.setRouteLeaveHook(this.props.route, this.routerWillLeave);
  //or this.context.router, depending on your app
}

routerWillLeave = (nextLocation) => {
  if (this.state.step > 1) {
    this.setState({step: this.state.step-1});
    return false;
  }
}

如果step更改大于1,上述操作将阻止路由更改。而是调用setState并将step减1,从而强制执行上一步骤。如果step等于1,那么在历史记录中回到上一页可能是有意义的,因为在步骤1之前没有上一步。

如果用户填写了表单中的某些数据(以防止丢失),您可能还有兴趣在实际返回上一页之前要求路由离开确认对话框。在这种情况下,您可以添加上面的代码:

routerWillLeave(nextLocation) {
  if (this.state.step > 1) {
    ...
  } else if (this.hasUnsavedData()) {
    return "You have unsaved data. Are you sure you want to leave?"
  }

其中hasUnsavedData()您要写的一些自定义函数会检查所有表单元素,并且仅当所有输入字段都为空时才返回false,否则true