React.js"隐藏元素并显示下一个元素"提交后

时间:2017-07-30 13:13:21

标签: javascript reactjs ecmascript-6

我正在使用Mad Libs游戏,向用户提出如下问题:

  

输入名词

用户填写正确的名称,点击提交,然后现在隐藏文本输入,并显示下一个问题。

我知道它处理条件渲染以使其工作,但我不确定如何以及从何处开始。我写了一个用户故事,试着在写出来的时候继续跟进,但仍然有点迷失。我的用户故事是

  

当用户输入文本并点击提交(或输入键)时,文本输入将被隐藏(但不会被删除或删除,因为输入的值用于传递道具),并显示带有新输入的下一个文本输入直到。当所有问题都得到解答时,会调用Madlibs组件。

除了上面的用户故事之外,所有内容都已构建完成并正常工作。我此时没有收到错误,我根本不知道如何为此编写条件函数。

这是我的代码:

import React, { Component } from 'react';
import styled from 'styled-components';
import Crawler from './crawler';

const NextQuestion = styled.div`
  position: absolute;
  color: white;
  display: block;
  margin-top: 108px;
`;

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value1: 'enter proper name',
      value2: 'noun',
      value3: 'enter another proper name',
      newValue: '',
      submitted: false,
      input1: 0,
      input2: 0,
      input3: 0,
      input4: 0,
      input5: 0,
      input6: 0,
      input7: 0
    };

    this.handleFirstChange = event => this.handleChange(event, 'value1');
    this.handleSecondChange = event => this.handleChange(event, 'value2');
    this.handleThirdChange = event => this.handleChange(event, 'value3');
    this.handleFourthChange = event => this.handleChange(event, 'value4');
    this.handleFifthChange = event => this.handleChange(event, 'value5');
    this.handleSixthChange = event => this.handleChange(event, 'value6');
    this.handleSeventhChange = event => this.handleChange(event, 'value7');
    this.handleSubmit = event => this._handleSubmit(event);
  }

  handleChange(event, type) {
    let newState = {};
    newState[type] = event.target.value;
    this.setState(newState);
  }

  _handleSubmit(event) {
    event.preventDefault();
    let toggle = this.state.visable;
    this.setState({ visable: !toggle });
  }

  render() {
    const divStyle = {
      marginTop: '50px',
      color: 'white',
      top: '25px',
      position: 'absolute'
    };
    let question = null;
    const show = this.state.visable;
    if (show) {
      question = (
        <div>
          <Crawler
            properName1={this.state.value1}
            noun1={this.state.value2}
            properName2={this.state.value3}
            properName3={this.state.value4}
            noun2={this.state.value5}
            personsName1={this.state.value6}
            noun3={this.state.value7}
          />
        </div>
      );
    }
    return (
      <div>
        <div style={divStyle}>
          <form onSubmit={this.handleSubmit}>
            <label>
              Proper Name:
              <input
                name="input1"
                type="text"
                value={this.state.value1}
                onChange={this.handleFirstChange}
              />
            </label>
            <label>
              Noun:
              <input
                name="input2"
                type="text"
                value={this.state.value2}
                onChange={this.handleSecondChange}
              />
            </label>
            <label>
              Another Proper Name:
              <input
                name="input3"
                type="text"
                value={this.state.value3}
                onChange={this.handleThirdChange}
              />
            </label>
            <label>
              And Another Proper Name:
              <input
                name="input4"
                type="text"
                value={this.state.value4}
                onChange={this.handleFourthChange}
              />
            </label>
            <label>
              Noun:
              <input
                name="input5"
                type="text"
                value={this.state.value5}
                onChange={this.handleFifthChange}
              />
            </label>
            <label>
              Person's Name:
              <input
                name="input6"
                type="text"
                value={this.state.value6}
                onChange={this.handleSixthChange}
              />
            </label>
            <label>
              Another Noun:
              <input
                name="input7"
                type="text"
                value={this.state.value7}
                onChange={this.handleSeventhChange}
              />
            </label>
            <input type="submit" value="Submit" />
          </form>
        </div>
        <NextQuestion>
          {question}
        </NextQuestion>
      </div>
    );
  }
}

export default NameForm;

我使用这个练习教我更多关于React和条件的知识。谢谢你的帮助。

1 个答案:

答案 0 :(得分:1)

问题列表

首先,您需要创建一个问题列表:>>> a.astype(int, value_on_error=0)

array

您可以通过设置数组的const QuestionsList = [ { // Your question title q: "Are you a human?", // Validate the user answer a: (answer) => (answer === 'yes'), // Force user to give a correct answer required: true // Add more properties ... }, ... ]; 的问题进行导航:

index

问题组件

  

当用户输入文本并点击提交时,文本输入将被隐藏(但不会删除或删除,因为输入的值用于传递道具),并且显示带有新输入的下一个文本输入,直到。

由于您只使用了输入this.state = { current: 0 } ... // Select current question QuestionList[this.state.current] // Select next question QuestionList[this.state.current + 1] // Select last question QuestionList[QuestionList.length - 1] ,因此您可以在所有问题中使用单个组件,而无需在此处理[text]

conditionals

React会通过 const RenderQuestion = ( <div> <h2>{question.q}</h2> <input type="text" value={this.state.value} onChange={this.handleChange} /> <button onClick={this.handleSubmit}> Submit </button> </div> ); 更新组件内容 这会产生state

的效果

下一个问题

  

因为this.props和this.state可以异步更新,所以你不应该依赖它们的值来计算下一个状态

要解决此问题,请使用hide previous / show next的第二种形式:

setState

请参阅:State Updates May Be Asynchronous

已完成

  

当回答完所有问题后,将调用Madlibs组件。

this.setState(prev => {

     // Get previous state
     const {value, current} = prev;

     //If input not empty
     if (value.length > 0) { 

            // Validate answer: true / false
            const validation =  questions[current].a(value);

            //If not last question
            return (prev.current < index) ?

            //Select next question / reset input
            { 
                current: prev.current + 1,
                value:''
            } :

            // else: Completed!
            { completed: true };

     }
   }); 

条件

  

如果条件为真,那么元素就在&amp;&amp;将出现在输出中。如果是假,React将忽略并跳过它。

{ this.state.completed ? <Madlibs /> : RenderQuestion }
  

有条件地呈现内联元素的另一种方法是使用JavaScript条件运算符:

condition === true  && element / method

请参阅:Inline If with Logical && Operator

实施例

&#13;
&#13;
condition ? true : false
&#13;
const QuestionsList = [
 {
  q: "What's your name?",
  a: (answer) => /^[A-Za-z\s]+$/.test(answer),
  
  // Force user to give a correct answer
  required: true
  
 },
 {
  q: "Type a color:",
  a: (answer) => {
      const colors = ['blue', 'green', 'red', 'yellow', 'black', 'brown', 'orange', 'pink', 'purple', 'white', 'gray']
      return colors.includes(answer);
      },
  required: true
  },
];

class Questionary extends React.Component {

    constructor(props){
        super(props);
        
        //Init state
        this.state = { 
            current: 0,
            value:'',
            completed: false,
            data: []
        };
        
        // Bind handlers
        this.handleSubmit =  this.handleSubmit.bind(this);
        this. handleChange =  this.handleChange.bind(this);
    }
    
     handleChange(event) {
        this.setState({value: event.target.value});
     }
    
     handleSubmit () {
       const {questions} = this.props;
       const index = questions.length - 1 ;
       let state = {};
  
       this.setState(prev => {
         // Vars
         const { value, current } = prev;
         const question = questions[current];
         const validation = question.a(value);
       
         //If input not empty
         if (value.length > 0) {
             
             // Debug validation
             !validation && console.log("Please enter a valid value!");
         
             //Force user to give the correct answer)
             if (question.required && validation == false) return state;  
                
             // Data for the template string
             let data = prev.data;
             data.push(value);
             
             //If not last question
             state = (prev.current < index) ?
             
             //Select next question and reset input
             { 
                 current: prev.current + 1,
                 value:'',
                 data
             } :
                 
             // else: Completed!
             { completed: true, data };
                
             return state;
         }
         
         // Debug input
         console.log("Empty input!");
       });
    }
    
    render() {
    
        // Get all questions
        const { questions } = this.props;
       
       //Select question
        const question = questions[this.state.current];
        
        // Question component
        const RenderQuestion = (
            <div>
                <h2>{question.q}</h2>
                <input type="text"
                       value={this.state.value}
                       onChange={this.handleChange}
                />
                <button onClick={this.handleSubmit}>
                    Submit
                </button>
          </div>
        );
        
        // Score component
        const RenderTemplates = (
            <div>
                <h2>Completed!</h2>
                <p>
                  This is the story of
                  <span>{this.state.data[0]}</span>
                  and how the
                  <span>{this.state.data[1]}</span> dragon...
                </p>
                <p>
               <span>{this.state.data[0]}</span> found a
               <span>{this.state.data[1]}</span> goblin in the woods and then...
                </p>
          </div>
        );
        
        return (
        <div>
            {
              this.state.completed ? 
              RenderTemplates : RenderQuestion
            }
         </div>
        );
    }
}

ReactDOM.render(<Questionary questions={QuestionsList}/>, document.getElementById("root"));
&#13;
#root {

    font-family: Arial, sans-serif;
    color: #252525

}

h2, input[type=text] {
   margin: 10px;
}

button {
 border: 0;
 border-radius: 3px;
 background: #416dea;
 padding: 5px 10px;
 color: #FFF;
 font-weight: bold;
 border-radius: 3px;
}

p {
 padding: 10px;
 background: #ddd;
}
p span {
padding: 2px 4px;
margin: 0 10px;
background: #FFF;
color: #416dea;
}
&#13;
&#13;
&#13;