Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PullToRefresh会导致Input的焦点消失, 从而无法输入 #3009

Open
qyuzh opened this issue Feb 22, 2025 · 0 comments
Open

PullToRefresh会导致Input的焦点消失, 从而无法输入 #3009

qyuzh opened this issue Feb 22, 2025 · 0 comments

Comments

@qyuzh
Copy link

qyuzh commented Feb 22, 2025

NutUI React 包名

@nutui/nutui-react

NutUI React 版本号

"@nutui/nutui-react-taro": "^2.6.14",

平台

weapp

重现链接

重现步骤

import Device from "@/components/device";
import Layout from "@/components/layout";
import { Button, PullToRefresh, Toast } from "@nutui/nutui-react-taro";
import { useEffect, useState } from "react";
import { DeviceType } from "@/data/types";
import pulldown from "@/assets/pull_down.png";
import finish from "@/assets/finish.png";
import "./index.scss";
import Taro, { useDidShow } from "@tarojs/taro";
import request from "@/apis/request";

const mockDeviceList: DeviceType[] = [];

const getDeviceList = async (onSuccess: (data: DeviceType[]) => void) => {
  const { ok, data, msg } = await request<DeviceType[]>(
    "/users/{user_id}/devices",
    "GET"
  );
  if (ok) {
    onSuccess(data!);
  } else {
    Toast.show("toast", {
      type: "fail",
      content: msg || "获取设备列表失败",
    });
  }
};

export default function Index() {
  const [deviceList, setDeviceList] = useState<DeviceType[]>(mockDeviceList);

  const onEditFinish = () => {
    getDeviceList(setDeviceList);
  };

  const onAddDevice = () => {
    Taro.scanCode({
      success: async (res) => {
        const { ok, msg } = await request<DeviceType>(
          "/users/{user_id}/devices",
          "POST",
          {
            device_id: res.result,
          }
        );
        if (ok) {
          getDeviceList(setDeviceList);
        } else {
          Toast.show("toast", {
            type: "fail",
            content: msg || "添加设备失败",
          });
        }
      },
      fail: (res) => {
        Toast.show("toast", {
          type: "fail",
          content: res.errMsg || "扫码失败",
        });
        getDeviceList(setDeviceList);
      },
    });
  };

  useEffect(() => {
    getDeviceList(setDeviceList);
  }, []);

  useDidShow(() => {
    getDeviceList(setDeviceList);
    Toast.show("toast", {
      type: "info",
      content: "添加设备失败",
    });
  });

  return (
    <Layout>
      <div className="add-device">
        <Button type="primary" block onClick={onAddDevice}>
          +
        </Button>
      </div>

      <div className="device-list">
        <PullToRefresh
          onRefresh={async () => {
            return await getDeviceList(setDeviceList);
          }}
          renderIcon={(status) => {
            return (
              <>
                {status === "pulling" && (
                  <img
                    alt=""
                    style={{ height: "26px", width: "26px" }}
                    src={pulldown}
                  />
                )}
                {status === "complete" && (
                  <img
                    alt=""
                    style={{ height: "26px", width: "26px" }}
                    src={finish}
                  />
                )}
              </>
            );
          }}
        >
          {deviceList.map((device) => (
            <Device key={device.id} {...device} onEditFinish={onEditFinish} />
          ))}
        </PullToRefresh>
      </div>
      <Toast id="toast" duration={2} />
    </Layout>
  );
}
import {
  Button,
  Cell,
  Form,
  Input,
  Picker,
  Popup,
  Toast,
} from "@nutui/nutui-react-taro";
import { ArrowRight } from "@nutui/icons-react-taro";
import "./index.scss";
import { useEffect, useRef, useState } from "react";
import { DeviceType } from "@/data/types";
import request from "@/apis/request";

interface Option {
  text: string;
  value: string;
}

interface DeviceProps extends DeviceType {
  onEditFinish: () => void;
  showEdit?: (show: boolean) => void;
}

export default function Device(props: DeviceProps) {
  const [showBasic, setShowBasic] = useState(false);
  const [toneOptions, setToneOptions] = useState<Option[]>([]);
  const [roleOptions, setRoleOptions] = useState<Option[]>([]);

  const onSubmit = async (values: {
    name: string;
    role: number[];
    tone: number[];
  }) => {
    const { ok } = await request<DeviceType>(
      `/users/{user_id}/devices/${props.id}`,
      "PUT",
      {
        name: values.name,
        agent: values.role[0],
        voice: values.tone[0],
      }
    );
    if (ok) {
      props.onEditFinish();
      setShowBasic(false);
      Toast.show("toast", {
        type: "success",
        title: "更新设备信息成功",
      });
    } else {
      Toast.show("toast", {
        type: "fail",
        title: "更新设备信息失败",
        content: "请稍后重试",
      });
    }
  };

  useEffect(() => {
    const fetch = async () => {
      {
        const { ok, data } = await request<{ id: string; name: string }[]>(
          "/users/{user_id}/voices",
          "GET"
        );
        if (ok) {
          setToneOptions(data!.map((v) => ({ text: v.name, value: v.name })));
        }
      }
      {
        const { ok, data } = await request<{ id: string; name: string }[]>(
          "/users/{user_id}/agents",
          "GET"
        );
        if (ok) {
          setRoleOptions(data!.map((v) => ({ text: v.name, value: v.name })));
        }
      }
    };
    fetch();
  }, []);

  return (
    <>
      <div
        className="device"
        onClick={() => {
          props.showEdit && props.showEdit(true);
          setShowBasic(true);
        }}
      >
        <div className="device-title">{`${props.name}(${props.battery_percentage}%)`}</div>
        <div className="device_subtitle">{props.agent}</div>
        <div className="device_subtitle">{props.voice}</div>
      </div>
      <Popup
        visible={showBasic}
        style={{ height: "80vh" }}
        position="bottom"
        onClose={() => {
          props.showEdit && props.showEdit(false);
          setShowBasic(false);
        }}
      >
        <Form
          labelPosition="right"
          footer={
            <>
              <Button nativeType="submit" block type="primary">
                提交
              </Button>
            </>
          }
          initialValues={{
            name: props.name,
            role: [props.agent],
            tone: [props.voice],
          }}
          onFinish={(values) => onSubmit(values)}
        >
          <Form.Item
            align="center"
            required
            label="名称"
            name="name"
            rules={[{ required: true, message: "请输名称" }]}
          >
            <Input
              className="nut-input-text"
              placeholder="请输名称"
              type="text"
            />
          </Form.Item>
          <Form.Item
            label="音色"
            name="tone"
            trigger="onConfirm"
            getValueFromEvent={(...args) => args[1]}
            onClick={(_event, ref: any) => {
              ref.open();
            }}
            rules={[{ required: true, message: "请选择音色" }]}
          >
            <Picker options={toneOptions}>
              {(value: any) => {
                return (
                  <Cell
                    style={{
                      padding: 0,
                    }}
                    className="nutui-cell--clickable"
                    title={
                      value.length
                        ? toneOptions.filter((po) => po.value === value[0])[0]
                            ?.text
                        : "请选择"
                    }
                    extra={<ArrowRight />}
                    align="center"
                  />
                );
              }}
            </Picker>
          </Form.Item>
          <Form.Item
            label="角色"
            name="role"
            trigger="onConfirm"
            getValueFromEvent={(...args) => args[1]}
            onClick={(_event, ref: any) => {
              ref.open();
            }}
            rules={[{ required: true, message: "请选择角色" }]}
          >
            <Picker options={roleOptions}>
              {(value: any) => {
                return (
                  <Cell
                    style={{
                      padding: 0,
                    }}
                    className="nutui-cell--clickable"
                    title={
                      value.length
                        ? roleOptions.filter((po) => po.value === value[0])[0]
                            ?.text
                        : "请选择"
                    }
                    extra={<ArrowRight />}
                    align="center"
                  />
                );
              }}
            </Picker>
          </Form.Item>
        </Form>
      </Popup>
    </>
  );
}

期望的结果是什么?

焦点不消失

实际的结果是什么?

焦点不消失

环境信息

No response

其他补充信息

No response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant