首页 > 解决方案 > 反应子/父组件 - onChange 事件只需要一个字符而不保留值

问题描述

在 ReactJS 中,在我的子组件中,输入 > 文本上的 onChange() 事件只取一个值,而不是在每次按键时保留以前的值。

我正在尝试以子形式捕获输入并希望将其传输给父级。实际上,我正在尝试将子表单重用于创建和编辑页面。

我的完整代码框在这里 https://codesandbox.io/embed/sleepy-stallman-fbyhh?fontsize=14

子组件

    import React, { Component } from "react";
    import { Form } from "react-bootstrap";

    export default class EmployeeForm extends Component {
      constructor(props) {
        super(props);
        console.log("this.props.employee ", this.props.employee);
      }

      /** Generic handle change events for all fields */
      handleChange = e => {
        this.props.employee[e.target.id] = e.target.value;
        console.log(e.target.value);
      };

      //   handleChange = (key, e) => {
      //     e.preventDefault();
      //     console.log(key);
      //     console.log(e.target.value);
      //     this.props.employee[key] = e.target.value;
      //   };

      render() {
        const { employee } = this.props;
        console.log("ef render ", employee.firstName);

        return (
          <div>
            <Form.Group controlId="firstName">
              <Form.Label>First name</Form.Label>
              <Form.Control
                type="text"
                value={employee.firstName}
                onChange={this.handleChange}
                placeholder="Enter first name"
              />
            </Form.Group>
            <Form.Group controlId="lastname">
              <Form.Label>Last name</Form.Label>
              <Form.Control
                type="text"
                value={employee.lastName}
                onChange={this.handleChange}
                placeholder="Enter last name"
              />
            </Form.Group>
            <Form.Group controlId="birthDate">
              <Form.Label>Date of birth</Form.Label>
              <Form.Control
                type="date"
                value={employee.birthDate}
                onChange={this.handleChange}
              />
            </Form.Group>
            <Form.Group controlId="hireDate">
              <Form.Label>Date of hire</Form.Label>
              <Form.Control
                type="date"
                value={employee.hireDate}
                onChange={this.handleChange}
              />
            </Form.Group>
            <Form.Group controlId="gender">
              <Form.Label>Gender</Form.Label>
              <Form.Control
                as="select"
                value={employee.gender}
                onChange={this.handleChange}
              >
                <option value="">Please select</option>
                <option value="F">Female</option>
                <option value="M">Male</option>
              </Form.Control>
            </Form.Group>
          </div>
        );
      }
    }

父组件

    import React from "react";
    import { Alert, Form, Col, Row, Button, Card } from "react-bootstrap";
    import EmployeeForm from "./EmployeeForm";
    import EmployeeService from "./services/EmployeeService";

    export default class CreateEmployee extends React.Component {
      constructor() {
        super();
        this.employeeService = new EmployeeService();
        this.state = {
          employee: {
            firstName: "",
            lastName: "",
            birthDate: "",
            hireDate: "",
            gender: ""
          }
        };
      }

      save = () => {
        console.log(this.state.values);
        this.employeeService
          .createEmployee(this.state.values)
          .then(result => {
            this.setState({ error: null });
          })
          .catch(err => {
            console.log(err);
            this.setState({ error: err });
          });
      };

      render() {
        console.log("reder : ", this.state.employee);

        return (
          <div>
            <Form>
              <Alert variant="primary">Employee</Alert>

              <Card style={{ width: "500px" }}>
                <Card.Header>Create Employee</Card.Header>
                <Card.Body>
                  <EmployeeForm employee={this.state.employee} />
                  <Row>
                    <Col>
                      <Button variant="primary" type="button" onClick={this.save}>
                        Create
                      </Button>
                    </Col>
                  </Row>
                </Card.Body>
              </Card>
            </Form>
          </div>
        );
      }
    }

标签: javascriptreactjs

解决方案


所以我浏览了codesandbox上的代码并进行了以下更改 - 明显的更改在顶部有注释:你可以在这里查看它们 - https://codesandbox.io/s/react-parent-child-1fif1?fontsize= 14

您不应执行以下操作:

  • 直接改变状态

  • 尝试从子组件的道具中改变父组件中的状态

EmployeeForm.js - 子组件

import React, { Component } from "react";
import { Form } from "react-bootstrap";

export default class EmployeeForm extends Component {
  constructor(props) {
    super(props);
  }
// create a handleChangle method here, that calls the handleChange from props
// So you can update the state in CreateEmployee with values from the form

  handleChange = e => {
    this.props.handleChange(e)
  };

  render() {
    const { employee } = this.props;
    // console.log("ef render ", employee.firstName);

    return (
      <div>
        <Form.Group controlId="firstName">
          <Form.Label>First name</Form.Label>
          <Form.Control
            type="text"
            value={employee.firstName}
            onChange={this.handleChange}
            placeholder="Enter first name"
          />
        </Form.Group>
        <Form.Group controlId="lastName">
          <Form.Label>Last name</Form.Label>
          <Form.Control
            type="text"
            value={employee.lastName}
            onChange={this.handleChange}
            placeholder="Enter last name"
          />
        </Form.Group>
        <Form.Group controlId="birthDate">
          <Form.Label>Date of birth</Form.Label>
          <Form.Control
            type="date"
            value={employee.birthDate}
            onChange={this.handleChange}
          />
        </Form.Group>
        <Form.Group controlId="hireDate">
          <Form.Label>Date of hire</Form.Label>
          <Form.Control
            type="date"
            value={employee.hireDate}
            onChange={this.handleChange}
          />
        </Form.Group>
        <Form.Group controlId="gender">
          <Form.Label>Gender</Form.Label>
          <Form.Control
            as="select"
            value={employee.gender}
            onChange={this.handleChange}
          >
            <option value="">Please select</option>
            <option value="F">Female</option>
            <option value="M">Male</option>
          </Form.Control>
        </Form.Group>
      </div>
    );
  }
}

CreateEmployee.js - 父组件

import React from "react";
import { Alert, Form, Col, Row, Button, Card } from "react-bootstrap";
import EmployeeForm from "./EmployeeForm";
import EmployeeService from "./services/EmployeeService";

export default class CreateEmployee extends React.Component {
  constructor() {
    super();
    this.employeeService = new EmployeeService();
    this.state = {
      employee: {
        firstName: "",
        lastName: "",
        birthDate: "",
        hireDate: "",
        gender: ""
      }
    };
  }

  // Create handleChange here and pass it to EmployeeForm as props
  // Use setState instead of mutating state
  handleChange = e => {
    this.setState({employee: {[e.target.id]: e.target.value}})
  };

  save = () => {
    console.log(this.state.values);
    this.employeeService
      .createEmployee(this.state.values)
      .then(result => {
        this.setState({ error: null });
      })
      .catch(err => {
        console.log(err);
        this.setState({ error: err });
      });
  };

  render() {
    console.log("reder : ", this.state.employee);

    return (
      <div>
        <Form>
          <Alert variant="primary">Employee</Alert>

          <Card style={{ width: "500px" }}>
            <Card.Header>Create Employee</Card.Header>
            <Card.Body>
              <EmployeeForm handleChange={this.handleChange} employee={this.state.employee} />
              <Row>
                <Col>
                  <Button variant="primary" type="button" onClick={this.save}>
                    Create
                  </Button>
                </Col>
              </Row>
            </Card.Body>
          </Card>
        </Form>
      </div>
    );
  }
}

注意:我只修复了这个问题所要求的错误——你可能仍然需要重构你的代码的某些部分。不要忘记不要直接改变状态。


推荐阅读