setState甚至不更新状态,甚至回调

时间:2019-11-11 23:08:47

标签: reactjs

在输入字段更改时,将调用处理程序函数并更新状态,但状态并未更新。我知道setState()是异步的,所以我将console.log放在了回调中。

以下是功能:

class WorkspaceEditModal extends React.PureComponent {
  constructor(props) {
    super(props);

    console.log(props.selectedWorkspace); // prints correct value
    this.state = {
      editWorkspaceName: props.selectedWorkspace,
      exists: false,
    };
  }

  handleEditChange = event => { // this handler is called
    console.log(event.target.value); // prints new value
    this.setState({ editWorkspaceName: event.target.value },
      () => {console.log(this.state.editWorkspaceName)}); // still prints old value
  };

  handleFocus = e => e.target.select();

  handleKeyPress = e => {
    if (e.key === 'Enter') {
      e.preventDefault();
      this.editWorkspace();
    }
  };

  render() {
    const { editWorkspaceName, exists } = this.state;
    let content;

    content = (
        <div className="save-workspace">
          <div className="modal-header">
            <div className="modal-title">
              <p>Rename Workspace</p>
            </div>
            <div className="modal-select">
              <span className="input-label">Workspace Name</span>
              <div>
                <input
                  className="name-input"
                  placeholder="Workspace Name"
                  type="text"
                  defaultValue={editWorkspaceName}
                  onChange={this.handleEditChange} // calls the handler on change
                  onFocus={this.handleFocus}
                  onKeyPress={this.handleKeyPress}
                  autoFocus
                />
                {notValid && (
                  <p className="invalid">
                    Only alphanumeric characters, hyphens, spaces, and
                    underscores are allowed.
                  </p>
                )}
              </div>
            </div>
          </div>
          <div className="modal-footer">
            <button
              type="button"
              className="btn btn-default"
              onClick={this.onCloseModal}
            >
              Cancel
            </button>
            <button
              type="button"
              className="btn btn-primary"
              onClick={this.editWorkspace}
              disabled={notValid}
            >
              Update
            </button>
          </div>
        </div>
      );

    const contentStyle = {
      width: '500px',
    };

    return (
      <Modal
        isOpen={true}
        onClose={this.onCloseModal}
        contentStyle={contentStyle}
        shouldCloseOnOverlayClick={true}
      >
        {content}
      </Modal>
    );
  }
}

我不知道为什么会这样。这太疯狂了。

谢谢您的帮助。

1 个答案:

答案 0 :(得分:-2)

您正在通过props传递输入的默认值。那应该是您输入的默认值。它不应更新子组件的状态。

状态应在父组件而不是子组件上更新。 handleEditChange(在示例中为handleChange)函数应放在父组件中,然后通过props向下传递到输入。您希望通过该父函数在props中更改props的值,以便setState正常工作。

您可以使用getDerivedStateFromProps,但是这里似乎没有必要。 https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html

class ParentWorkSpaceEditModal extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      editWorkspaceName: 'whatever your original value is',
      exists: false,
    };
  }

  handleChange = event => {
    this.setState({ editWorkspaceName: event.target.value });
  };

  render() {
    const { editWorkspaceName, exists } = this.state;
    return (
      <ChildWorkspaceEditModal editWorkspaceName={editWorkspaceName} exists={exists} handleChange={this.handleChange} />
    )
  }
}

const ChildWorkspaceEditModal = ({ editWorkspaceName, exists, handleChange )} => {
  content = (
    <div className="save-workspace">
      <div className="modal-header">
        <div className="modal-title">
          <p>Rename Workspace</p>
        </div>
        <div className="modal-select">
          <span className="input-label">Workspace Name</span>
          <div>
            <input
              className="name-input"
              placeholder="Workspace Name"
              type="text"
              value={editWorkspaceName}
              onChange={handleChange}
            />
            {notValid && (
              <p className="invalid">
              Only alphanumeric characters, hyphens, spaces, and underscores are allowed.
              </p>
             )}
          </div>
        </div>
      </div>
      <div className="modal-footer">
        <button
          type="button"
          className="btn btn-default"
          onClick={this.onCloseModal}
        >
          Cancel
         </button>
         <button
           type="button"
           className="btn btn-primary"
           onClick={this.editWorkspace}
           disabled={notValid}
         >
          Update
         </button>
       </div>
     </div>
  );

  const contentStyle = {
    width: '500px',
  };

  return (
      <Modal
        isOpen={true}
        onClose={this.onCloseModal}
        contentStyle={contentStyle}
        shouldCloseOnOverlayClick={true}
      >
        {content}
      </Modal>
    )
}