React 路由器取决于 React 组件的状态 [英] React router depending on the state of the React component

查看:40
本文介绍了React 路由器取决于 React 组件的状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 react-router 有问题.

我的路由文件如下:

const 路由 = (<Route path="/" component={App}><IndexRoute 组件={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" 组件={RegistrationStepThree}/><Route path="/registration-step-four" component={RegistrationStepFour}/></路线><Route path="reset-password" component={PasswordReset}/></路线>);

我有一个大组件注册,它有四个步骤.然后点击提交按钮,状态会发生变化,并显示下一步.

注册组件代码为:

onButtonClick(name, event) {event.preventDefault();开关(名称){案例stepFourConfirmation":this.setState({步骤: 1});休息;案例stepTwoNext":this.setState({step: 3, errors: {}});休息;案例stepThreeFinish":this.setState({步骤: 4});休息;默认:this.setState({step: 2, errors: {}});}}使成为() {const languageReg = this.props.currentLanguage.default.registrationPage;让 formStep = '';让 step = this.state.step;开关(步骤){情况1:formStep = (<RegistrationFormStepOne user={this.state.user}onChange={this.setUser}onButtonClick={this.onButtonClick}onClick={this.changeStep}错误={this.state.errors}/>);休息;案例2:formStep = (<RegistrationFormStepTwo user={this.state.user}onChange={this.setUser}onButtonClick={this.onButtonClick}onClick={this.changeStep}错误={this.state.errors}/>);休息;案例3:formStep = (<RegistrationFormStepThree user={this.state.user}onFileChange={this.onFileChange}onButtonClick={this.onButtonClick}onClick={this.changeStep}错误={this.state.errors}文件={this.state.files}fileChosen={this.state.selectedFile}/>);休息;默认:formStep = (<RegistrationFormStepFour user={this.state.user}onChange={this.setUser}onChangeCheckboxState={this.changeCheckboxState}emailNotificationsState={this.state.user.emailNotifications}termState={this.state.user.terms}smsNotificationsState={this.state.user.smsNotifications}onButtonClick={this.onButtonClick}onClick={this.changeStep}错误={this.state.errors}/>);}返回 (<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="联系表单"><div className="容器"><div className="row"><div className="col-md-10 col-md-offset-1 col-md-offset-right-1">{React.cloneElement(formStep, {currentLanguage: languageReg})}

);}

但是,例如,如果我正在执行第三步,然后在浏览器中单击返回,我将被重定向到主页.有没有什么办法让反应路由器只到上一步蚂蚁而不到主页?还是用states来改变form step就不行了?

解决方案

您可以使用 routerWillLeave 钩子来做到这一点.在官方react-router文档.

您可以这样做:

componentDidMount = () =>{this.props.router.setRouteLeaveHook(this.props.route, this.routerWillLeave);//或 this.context.router,取决于你的应用}routerWillLeave = (nextLocation) =>{如果 (this.state.step > 1) {this.setState({step: this.state.step-1});返回假;}}

如果 step 更改大于 1,则上述内容将阻止路由更改.而是调用 setState 并且 step 减 1,强制渲染上一步.如果 step 等于 1,那么实际上返回历史记录到上一页可能是有意义的,因为在 step-1 之前没有上一步.

<小时>

如果用户在您的表单中填写了一些数据(以防止丢失),您可能还想在实际返回上一页之前询问是否有路线离开确认对话框.在这种情况下,您可以添加到上面的代码中:

routerWillLeave(nextLocation) {如果 (this.state.step > 1) {...} else if (this.hasUnsavedData()) {return "您有未保存的数据.您确定要离开吗?"}

其中 hasUnsavedData() 您将编写一些自定义函数来检查所有表单元素并仅在所有输入字段为空时返回 false,否则返回 true.

I have a problem with react-router.

My routes file is as follows :

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>
);

I have one big component Registration which has four steps. And by click on the submit button the state changes and the next step shows.

Registration component code is :

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

But if I'm on a for example third step and I click back in the browser I'm redirected to the home page. Is there any way that react router goes only to the previous step ant not to the homepage? Or it can't be done if I use states to change the form step?

解决方案

You could do this with the routerWillLeave hook. Read more about it on the official react-router documentation.

Here's what you could do:

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;
  }
}

The above will prevent route change if the step change is greater than one. Instead setState is called and step is reduced by 1, forcing a render of the previous step. If step is equal to 1, then it probably makes sense to actually go back in the history to the previous page, since there is no previous step before step-1.


You might also be interested in asking for a route-leave confirmation dialog before actually going back to the previous page if the user has filled in some data in your form (to prevent it from being lost). In that case you could add to the above code:

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

Where hasUnsavedData() some custom function you would write that checks all your form elements and returns false only if all input fields are empty, otherwise true.

这篇关于React 路由器取决于 React 组件的状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆