2016-06-09 4 views
1

У меня проблема с маршрутизатором.React router в зависимости от состояния компонента React

Мои маршруты файл выглядит следующим образом:

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

Вы можете сделать это с помощью крюка 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, то, вероятно, имеет смысл вернуться в историю на предыдущую страницу, так как перед шагом нет предыдущего шага.


Вы также можете быть заинтересованы в выяснении для диалога подтверждения на маршрут в отпуске перед тем как вернуться к предыдущей странице, если пользователь заполнил некоторые данные в форме (чтобы предотвратить его потерянным). В этом случае вы могли бы добавить в приведенном выше коде:

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.

+0

Я получаю _TypeError: Не могу прочитать свойство 'setRouteLeaveHook' из undefined_ – Boky

+0

попробуйте 'this.context.router .....' вместо этого. Поэтому замените «реквизит» на «контекст». – Chris

+0

Я добавил 'RegistrationPage.contextTypes = { router: PropTypes.object };' чтобы сделать контекст доступным. Но теперь я получаю _Uncaught TypeError: Не могу прочитать свойство «step» undefined_. – Boky