如何 return 用户输入做出反应?

How to return user input in react?

我是 React 和一般编码的新手,我正在尝试构建这个简单的抽认卡应用程序以更好地理解 React。我知道这段代码非常糟糕,它可能应该被分解成更多的组件,但我不知道如何将事件处理程序添加到提交按钮,这将创建一个闪卡,一侧有定义,术语另一方面,当单击卡片时,它会从定义变为术语。感谢任何反馈,如果这个问题很愚蠢,我提前道歉。

class flashcard extends Component {
  constructor(props) {
    super(props);
    this.state = {
      definition: "",
      term: "",
    };
  }
  createCard = () => {
    this.setState({
      definition: "test",
    });
  };

  render() {
    return (
      <div>
        <Navbar bg="primary" variant="dark">
          <Navbar.Brand>Flashcard</Navbar.Brand>
          <Nav className="mr-auto">
            <Button style={this.buttonstyles} variant="outline-light">
              Add Card
            </Button>
          </Nav>
        </Navbar>
        <Card style={this.styles}>
          <Card.Img variant="top" />
          <Card.Body>
            <Form>
              <Form.Group controlId="formBasicEmail">
                <Form.Label>definition</Form.Label>
                <Form.Control type="definition" placeholder="definition" />
              </Form.Group>

              <Form.Group controlId="formBasicPassword">
                <Form.Label>term</Form.Label>
                <Form.Control type="term" placeholder="term" />
              </Form.Group>
              <Button variant="primary" type="submit" onClick={this.createCard}>
                Submit
              </Button>
            </Form>
          </Card.Body>
        </Card>
        <Button style={this.previoussytle} variant="primary">
          Previous
        </Button>
        <Button style={this.nextsytle} className="m-2" variant="primary">
          Next
        </Button>
      </div>
    );
  }

正如评论员所提到的,在这种情况下您不需要表格。您只需要以输入的当前值的形式更新状态数组。混合提交和 onClick() 处理程序很少是一个好主意。

@qudrat 在他的 codesandbox 中给了你一个很好的起点。它比 React 更地道,而且是一个很好的模型。

您可以通过多种方式构建它,使用或不使用表单。我选择使用表单和 controlled components 来处理 <input> 元素。

使用这种布局,我们需要为每张卡片跟踪三个项目:

  • 术语(字符串)
  • 定义(字符串)
  • 翻转(布尔值)

所有三个项目都将在一个卡片对象中,看起来像这样:

{
  term: 'vcs',
  definition: 'version control system',
  flipped: false
}

我们还需要一个空数组来存储所有的卡片。所以应用程序的初始状态将如下所示:

state = {
  term: "",
  definition: "",
  cards: []
};

termdefinition 使用 handleChange 事件处理程序更新。

提交术语和定义时(通过handleSubmit),卡片将添加到cards数组。

事件处理程序 handleClick 将处理每张卡片的 flipped 属性 的切换。

然后我们可以使用 conditional rendering 来显示每张卡片的术语或定义。

{c.flipped ? c.definition : c.term}

工作示例:

class App extends React.Component {
  state = {
    term: "",
    definition: "",
    cards: []
  };
  
  // Set state for input elements using "Computed property names"
  handleChange = e => {
    this.setState({
      [e.target.name]: e.target.value
    });
  };

  // Toggle each card
  handleClick = index => {
    const updatedCards = this.state.cards;
    updatedCards[index].flipped = !updatedCards[index].flipped;
    this.setState({
      cards: updatedCards
    });
  };
  
  // Add a card to the array, then clear input elements
  handleSubmit = e => {
    e.preventDefault();
    this.setState(state => {
      return {
        cards: [
          ...state.cards,
          { term: state.term, definition: state.definition, flipped: false }
        ],
        term: '',
        definition: ''
      };
    });
  };

  render() {
    return (
      <React.Fragment>
        <form className="card-form" onSubmit={this.handleSubmit}>
          <input
            type="text"
            name="term"
            onChange={this.handleChange}
            placeholder="term"
            value={this.state.term}
          />

          <input
            type="text"
            name="definition"
            onChange={this.handleChange}
            placeholder="definition"
            value={this.state.definition}
          />
          <button>Add</button>
        </form>
        <div className="card-grid">
          {this.state.cards.map((c, i) => (
            <div
              key={c.term + i}
              className="card"
              onClick={() => this.handleClick(i)}
            >
              {c.flipped ? c.definition : c.term}
            </div>
          ))}
        </div>
      </React.Fragment>
    );
  }
}

ReactDOM.render(<App/>, document.getElementById('root'));
body {
  font-family: Arial, Helvetica, sans-serif;
}

.card-grid {
  padding: 0.2rem;
  display: flex;
  flex-wrap: wrap;
}

.card {
  border: 2px solid gray;
  border-radius: 4px;
  padding: 10px;
  width: 80px;
  height: 90px;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
  margin: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

注意:为了使示例简单,我没有包括 React Bootstrap,但是在您的最终项目中实施它应该不会有太多问题。