Навигация по компонентам без маршрутизации в React/Redux

Это может быть запутанным, так что терпите меня. Я только начинаю изучать React/Redux и управлять состоянием. Я хочу создать небольшое приложение, которое не использует маршрутизацию, которая выглядит следующим образом:

введите описание изображения здесь

Не отличается от мастера установки.

Пользователю будет предложено ответить на вопрос на каждой странице, а затем нажать кнопку для перехода вперед или назад. В конце пользователь увидит список своих ответов.

Я полагаю, что состояние будет выглядеть примерно так:

{
    steps: [
        { prompt: 'Question in step 1', answer: null },
        { prompt: 'Question in step 2', answer: null },
        { prompt: 'Question in step 3', answer: null }
    ],
    currentStepNumber: 0,
    currentStepData: { prompt: 'Question in step 1', answer: null }
}

Продвижение вперед / назад должно увеличиваться / уменьшаться currentStepNumber в то время как currentStepData должен показать, скажем steps[0], Кроме того, ответы должны быть сохранены во время навигации. Наконец, все результаты должны быть видны на последней странице.

Я действительно ломаю голову над тем, как сделать это без маршрутизации, просто передавая реквизит между компонентами и контейнерами.

Приведенный выше объект состояния - это попытка, которая выглядит так, как будто она может сработать, но я чувствую, что не понимаю этого.

Конкретные вопросы:

  • Как показать / скрыть компоненты при "навигации" без маршрутов?
  • Должен ли контейнер результатов просто скрываться все время, пока не будет достигнут последний шаг?
  • Как мне спроектировать состояние так, чтобы я знал, что шаг N является последним шагом в мастере и, следовательно, должен отображаться контейнер результатов?

1 ответ

Решение

Как показать / скрыть компоненты при "навигации" без маршрутов?

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

const Step1 = ({prompt, onNextStep}) => (
  <div>
    <h1>{prompt}</h1>
    <button type="button" className="btn btn-info" onClick={onNextStep}>Next</button>
  </div>
);

const Step2 = ({prompt, onNextStep, onPrevStep}) => (
  <div>
    <h1>{prompt}</h1>
    <button type="button" className="btn btn-info" onClick={onPrevStep}>Prev</button>
    &nbsp;
    <button type="button" className="btn btn-info" onClick={onNextStep}>Next</button>
  </div>
);

const Step3 = ({prompt, onPrevStep, onSubmit}) => (
  <div>
    <h1>{prompt}</h1>
    <button type="button" className="btn btn-info" onClick={onPrevStep}>Prev</button>
    &nbsp;
    <button type="button" className="btn btn-info" onClick={onSubmit}>Submit</button>
  </div>
);

const Results = ({prompt, children, onReset}) => (
  <div>
    <h1>{prompt}</h1>
    {children}
    <button type="button" className="btn btn-info" onClick={onReset}>Reset</button>
  </div>
);


class App extends React.Component {

    state = {
      step: 1,
      steps: [
        {
          prompt: 'Prompt 1',
          answer: ''
        },
        {
          prompt: 'Prompt 2',
          answer: ''
        },
        {
          prompt: 'Prompt 3',
          answer: ''
        },
      ],
    };

    onNextStep = () => this.setState({
      step: this.state.step + 1
    });

    onPrevStep = () => this.setState({
      step: this.state.step - 1
    });

    onSubmit = () => this.setState({
      step: null
    });

    onReset = () => this.setState({
      step: 1
    });

    render() {
      const { step, steps } = this.state;
      const { prompt } = step ? steps[step-1] : '';
      if (step === 1) {
        return (
          <Step1
            prompt={prompt}
            onNextStep={this.onNextStep}
          />
        );
      }
      if (step === 2) {
        return (
          <Step2
            prompt={prompt}
            onNextStep={this.onNextStep}
            onPrevStep={this.onPrevStep}
          />
        );
      }
      if (step === 3) {
        return (
          <Step3
            prompt={prompt}
            onPrevStep={this.onPrevStep}
            onSubmit={this.onSubmit}
          />
        );
      }
      if (step === null) {
        return (
          <Results 
            prompt="These are results" 
            onReset={this.onReset}
          >
            <p>Drop results here as children</p>
          </Results>
        );
      }

    }
}

ReactDOM.render(<App />, document.getElementById('root'));                
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/css/bootstrap.css" />

<div id="root"></div>

Должен ли контейнер результатов просто скрываться все время, пока не будет достигнут последний шаг?

Опять же, следуя рекомендациям условного рендеринга, вы, вероятно, не захотите "скрывать", а вместо этого визуализируете контейнер результатов, если выполняется определенное условие. В моем примере, контейнер результатов отображается, когда переменная состояния step равно null,

Как мне спроектировать состояние так, чтобы я знал, что шаг N является последним шагом в мастере и, следовательно, должен отображаться контейнер результатов?

Ваш государственный дизайн, кажется, в порядке. Вы можете проверить, достигли ли вы последнего шага, просто сравнив this.state.steps.length в this.state.step, Если они равны, вы достигли последнего шага.

Другие вопросы по тегам