3

我是 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>
    );
  }
4

2 回答 2

2

您可以通过多种方式构建它,无论是否使用表单。我选择使用表单和 受控组件来处理<input>元素。

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

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

所有三个项目都将位于一个卡片对象中,如下所示:

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

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

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

和使用事件处理程序term更新。definitionhandleChange

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

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

然后我们可以使用条件渲染来显示每张卡片的术语或定义。

{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,但在最终项目中实现它应该不会有太多问题。

于 2020-06-05T14:59:33.277 回答
2

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

@qudrat 在他的代码盒中为您提供了一个很好的起点。React 和一个好的模型更习惯用语。

于 2020-06-05T01:00:39.670 回答