【问题标题】:Navigating components without routing in React/Redux在 React/Redux 中导航组件而不使用路由
【发布时间】:2018-05-29 06:34:29
【问题描述】:

这可能很复杂,所以请耐心等待。我刚刚开始学习 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]。此外,应在导航时保存响应。 最后,所有结果都应该在最终的“页面”上可见。

我真的很想知道如何在不通过简单地在组件和容器之间传递 props 的情况下做到这一点。

上面的状态对象是一个尝试,看起来它可能有效,但我觉得我没有得到它。

具体问题:

  • 如何在没有路线的“导航”时显示/隐藏组件?
  • 是否应该一直隐藏结果容器,直到到达最后一步?
  • 如何设计状态以便我知道步骤 N 是向导中的最后一步,因此需要显示结果容器?

【问题讨论】:

    标签: javascript reactjs redux react-routing


    【解决方案1】:

    如何在没有路线的“导航”时显示/隐藏组件?

    您应该使用所谓的conditional rendering。在您的情况下,组件可以在没有路由器的情况下像这样实现:

    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.lengththis.state.step 进行比较来检查您是否到达了最后一步。如果它们相等,则您已到达最后一步。

    【讨论】:

    • 感谢您的精彩回答。当您说“像孩子一样丢在这里”时,您的意思是简单地列出state.steps 的内容吗?另外,我将如何将答案添加到所述哈希中?查看当前步骤并从某个输入字段中获取值?
    • React 有一个特殊的 prop 叫做 children。当您不提前知道需要在组件内呈现哪些内容时使用。通过说“像孩子一样放弃”,我的意思是您可能希望您的 呈现在steps 期间收集的答案。要将答案添加到所述散列,您需要修改onNextStep 方法,以便它负责将结果保存到应用程序的state。是的,确切地说,在每个步骤中,您都需要从步骤 或任何元素中提取值。
    猜你喜欢
    • 2017-12-17
    • 1970-01-01
    • 2017-01-23
    • 2018-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    相关资源
    最近更新 更多