【问题标题】:React router depending on the state of the React componentReact 路由器取决于 React 组件的状态
【发布时间】:2016-06-09 10:56:28
【问题描述】:

我的 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>
    );
}

但是,例如,如果我在执行第三步并在浏览器中单击返回,我将被重定向到主页。有什么方法可以让反应路由器只进入上一步蚂蚁而不是主页?或者如果我使用状态更改表单步骤就无法完成?

【问题讨论】:

    标签: reactjs react-router


    【解决方案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 更改大于一,上述内容将阻止路由更改。相反,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

    【讨论】:

    • 我收到 TypeError: Cannot read property 'setRouteLeaveHook' of undefined
    • 我添加了RegistrationPage.contextTypes = { router: PropTypes.object }; 以提供上下文。但现在我得到 Uncaught TypeError: Cannot read property 'step' of undefined
    • 好的,尝试使用 ES6 函数。将routerWillLeave(nextLocation) { 替换为routerWillLeave = (nextLocation) =&gt; {
    • 我把所有东西都放在了 componentDidMount componentDidMount() { this.context.router.setRouteLeaveHook(this.props.route, (nextLocation) =&gt; { if (this.state.step &gt; 1) { this.setState({step: this.state.step - 1}); return false; } }); } 现在我收到警告不要在 componentDidMount 中使用 setState,但它起作用了。 :)
    • @Boky,听起来您可能有一个与这个关于历史的特定问题无关的 问题。发布一个新问题:)
    猜你喜欢
    • 2018-11-26
    • 1970-01-01
    • 2019-06-27
    • 1970-01-01
    • 2020-08-16
    • 1970-01-01
    • 2019-11-26
    • 1970-01-01
    • 2017-02-02
    相关资源
    最近更新 更多