2

我有一个名为 App 的反应组件,其中包含 2 个组件:Form 和 Table。并且它们都是受控组件。

在表单中,有一个输入元素和一个按钮。
input 元素有一个 onChange 属性;每当值更改时,它都会更改应用程序状态中的值。
该按钮具有由 App 组件提供的 onClick 属性;每当单击按钮时,状态的 firstNames(它是一个数组)将与 firstname 的状态值相加。

问题是当我单击按钮时,它会抛出一个错误,说我没有传入数组并且它没有 map 方法,即使在回调中,更新的状态确实显示了一个数组。

下面是代码:

function Form(props) {
  return (
    <form>
      <label>
        Item: <input value={props.value} onChange={props.handleChange} />
      </label>
      <button onClick={props.handleClick}>Submit</button>
    </form>
  );
}

function Table(props) {
  let firstNames = props.names.map((item, index) => {
    return (
      <tr key={index}>
        <td>{item}</td>
      </tr>
    );
  });
  return (
    <table>
      <thead>
        <tr>
          <th>First Name</th>
        </tr>
      </thead>
      <tbody>{firstNames}</tbody>
    </table>
  );
}

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      inputField: "",
      firstNames: ["Joey", "Chloe"],
    };
    this.handleChange = this.handleChange.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }
  handleChange(event) {
    this.setState({ inputField: event.target.value });
  }
  handleClick() {
    this.setState(
      {
        firstNames: this.state.firstNames.push(this.state.inputField),
      },
      console.log(this.state.firstNames)
    );
  }
  render() {
    return (
      <div>
        <Form
          value={this.state.inputField}
          handleChange={this.handleChange}
          handleClick={this.handleClick}
        />
        <Table names={this.state.firstNames} />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
4

1 回答 1

1

push改变原始数组,但它返回length更新数组的,因此,在初始推送之后,你的firstNames内部状态将是一个数字,它没有map

你不应该改变状态变量,你应该在添加新名称时创建一个新数组,例如,像这样:

this.setState({
    firstNames: [...this.state.firstNames, this.state.inputField]
})

完整的示例代码将如下所示:

function Form(props) {
  return (
    <form onSubmit={props.handleClick}>
      <label>
        Item: <input value={props.value} onChange={props.handleChange} />
      </label>
      <button>Submit</button>
    </form>
  );
}

function Table(props) {
  let firstNames = props.names.map((item, index) => {
    return (
      <tr key={index}>
        <td>{item}</td>
      </tr>
    );
  });
  return (
    <table>
      <thead>
        <tr>
          <th>First Name</th>
        </tr>
      </thead>
      <tbody>{firstNames}</tbody>
    </table>
  );
}

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      inputField: "",
      firstNames: ["Joey", "Chloe"],
    };
    this.handleChange = this.handleChange.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }
  handleChange(event) {
    this.setState({ inputField: event.target.value });
  }
  handleClick( e ) {
    event.preventDefault();
    this.setState(
      {
        firstNames: [...this.state.firstNames, this.state.inputField],
        inputField: ''
      }, () => console.log(this.state.firstNames) );
  }
  render() {
    return (
      <div>
        <Form
          value={this.state.inputField}
          handleChange={this.handleChange}
          handleClick={this.handleClick}
        />
        <Table names={this.state.firstNames} />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<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>

以下两件事我仍然在您的代码中更新:

添加了type="button"以便不会发生提交

<button type="button" onClick={props.handleClick}>Submit</button>

更改了setState用于记录的回调

this.setState({
  firstNames: [...this.state.firstNames, this.state.inputField],
  inputField: ''
}, () => console.log(this.state.firstNames) );

当您以原始方式执行此操作时,console.log将在您确定setState呼叫确实发生之前触发。

另一个注意事项可能是使用indexfor 键可能会导致事后出现问题(无论是排序还是删除项目),键应该是唯一的。在这段代码中,它只是一个提示

于 2020-06-10T22:29:15.310 回答