将函数传递给语义 ui clearable prop

Pass function to semantic ui clearable prop

我的应用程序有一小部分呈现下拉选择,因此用户可以在应用程序中查看有关库版本的一些简要信息。

第一个下拉菜单供用户选择他们想要查看的内容,为简洁起见,我只是为这个问题添加了相关选项。

第二个下拉列表呈现与 deviceIds 有关的已获取数字列表。这些 deviceIds 是从子 class 中获取的,然后通过道具传递给父 class。

现在,在 Semantic-UI-React 中,他们有一个带有 clearable 道具的下拉模块,我在这个填充了 deviceIds 的下拉菜单中使用了它。在下面 VersionNumber class 中,您可以看到为上述下拉列表定义的道具。

clearable 属性允许用户从下拉列表中删除选定的输入。但是,在我的应用程序中,当输入被删除时,它会调用我不想要的 onChange 函数。我尝试将自定义更改函数传递给 clearable 道具,我试图将状态变量 deviceId 重置回未定义的值,如果它是 "cleared" 由用户。

这可能吗?我很确定我采用了正确的方法,但可能会遇到 onChange 函数在 clearable 传递函数之前触发的问题。

我有一个可以重现 this problem here.

的 codesandbox
import React, { Component } from "react";
import ReactDOM from "react-dom";
import axios from "axios";

import {
  Dropdown,
  Form,
  Divider,
  Input,
  Message,
  Loader
} from "semantic-ui-react";

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      viewSelection: "",
      deviceId: "",
      versionNum: "",
      isLoading: true
    };
  }

  handleViewSelection = (e, { value }) => {
    this.setState({ viewSelection: value }, () => {
      console.log("view election --> ", this.state.viewSelection);
    });
  };

  onDeviceIdChange = async (e, { value }) => {
    console.log("device id value -->", value);
    this.setState({ deviceId: value }, () => {
      console.log(
        "deviceId value updated to state on select -->",
        this.state.deviceId
      );
    });
    try {
      const { data } = await axios.get(`/deviceId/${value}`);
      const version = data.data.versionNumber;
      this.setState({ versionNum: version.version, isLoading: false }, () => {
        console.log("callback from admin version fetch", this.state.versionNum);
      });
    } catch (error) {
      console.error(Error(`Error getting the selected deviceId ${error.message}`));
    }
  };

  handleClear = () => {
    this.setState({ deviceId: "" }, () => {
      console.log("handleClear function fired");
    });
  };

  render() {
    const { viewSelection, deviceId, versionNum, isLoading } = this.state;
    return (
      <div
        style={{ display: "flex", minHeight: "100vh", flexDirection: "column" }}
      >
        <div style={{ flex: 1 }}>
          <div
            style={{
              display: "flex",
              flexDirection: "column",
              justifyContent: "center",
              alignItems: "center",
              flex: "1"
            }}
          >
            <div style={{ width: "1000px" }}>
              <Divider style={{ marginTop: "7em" }} horizontal>
                View Data
              </Divider>
              <Message style={{ marginTop: "2em" }} info>
                <Message.Header>
                  Want to see more specific information? Log in &nbsp;
                  <a href="/">here</a>.
                </Message.Header>
              </Message>
              <Form.Field style={{ marginTop: "2em" }}>
                <label>Select data to view</label>
                <Dropdown
                  scrolling
                  placeholder="Pick an option"
                  value={viewSelection}
                  fluid
                  selection
                  multiple={false}
                  search
                  options={viewOptions}
                  onChange={this.handleViewSelection}
                />
              </Form.Field>

              {this.state.viewSelection && (
                <div style={{ marginTop: "2em" }}>
                  {viewSelection && viewSelection === "versionNumber" ? (
                    <>
                      <VersionNumber
                        onDeviceIdChange={this.onDeviceIdChange}
                        deviceId={deviceId}
                        handleClear={this.handleClear}
                      />
                      <div>
                        <label style={{ display: "block", marginTop: "2em" }}>
                          Version Number
                        </label>
                        {isLoading ? (
                          <Loader active inline="centered" />
                        ) : (
                          <Input value={versionNum} fluid readOnly />
                        )}
                      </div>
                    </>
                  ) : null}
                </div>
              )}
            </div>
          </div>
        </div>
      </div>
    );
  }
}

class VersionNumber extends Component {
  constructor(props) {
    super(props);

    this.state = {
      deviceId: "",
      deviceIds: []
    };
  }

  async componentDidMount() {
    await this.getDeviceIds();
  }

  getDeviceIds = async () => {
    try {
      const { data } = await axios.get("/deviceIds");
      console.log("device IDs --> ", data);
      const deviceIds = data.data.deviceIds;
      this.setState(
        {
          deviceIds: deviceIds
        },
        () => {
          console.log(
            "setState callback with updatesd deviceIds state -->",
            this.state.deviceIds
          );
        }
      );
    } catch (error) {
      console.error(Error(`Error getting deviceIds: ${error.message}`));
    }
  };

  render() {
    const { onDeviceIdChange, deviceId, handleClear } = this.props;
    const { deviceIds } = this.state;

    return (
      <Form.Field required>
        <label style={{ display: "block" }}>Device Id</label>
        <Dropdown
          id="deviceId"
          value={deviceId}
          onChange={onDeviceIdChange}
          selection
          fluid
          placeholder="Please select an device id"
          clearable={handleClear}
          options={deviceIds.map(id => {
            return {
              text: id.id,
              value: id.id,
              key: id.id
            };
          })}
          style={{ marginTop: ".33", marginBottom: "2em" }}
        />
      </Form.Field>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

clearable 道具需要一个 boolean 值。您可以更改 onChange 回调以考虑 value 将作为 null / undefined

传入的场景

可以如下修改函数以重置deviceId并阻止API调用

onDeviceIdChange = async (e, { value }) => {

  // VALUE WILL BE PASSED IN AS "" WHEN THE CLEAR OPTION IS CLICKED
  console.log("device id value -->", value);
  this.setState({ deviceId: value }, () => {
    console.log(
      "deviceId value updated to state on select -->",
      this.state.deviceId
    );
  });

  // THIS IS THE CONDITION TO CATCH THE CLEARABLE INVOCATION
  if(!value) {
    this.handleClear();
    return;
  } 

  ...
};

if(!value) return; 将此条件视为可清除选项将调用的执行。您可以在 return 之前调用任何内容,以确保您的应用程序以您期望的方式处理清除选项。