Навигация по компонентам без маршрутизации в 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>
<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>
<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
, Если они равны, вы достигли последнего шага.