使用 useState hook 初始化值不能生效?

发布于 2022-09-12 02:26:01 字数 5384 浏览 18 评论 0

在自定义表单控件中。接受从表单中传过来的值,修改后赋给 useState 作为初始值,无效,求指点

案例地址:
https://codesandbox.io/s/biao...

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import { Form, Input, Button, Upload, message } from "antd";
import { PlusOutlined } from "@ant-design/icons";

import "antd/dist/antd.css";

const images = [
  "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180615/5ad83a4fN6ff67ecd.jpg!cc_350x449.jpg",
  "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180615/xiaomi.jpg"
];

// 根据名称获取文件
function getFileExtendingName(filename = "") {
  // 文件扩展名匹配正则
  // eslint-disable-next-line
  const reg = /\.[^\.]+$/;
  const matches = reg.exec(filename);
  if (matches) {
    return matches[0].toLocaleLowerCase();
  }
  return "";
}

/**
 * 多文件上传 添加限制大小、个数、以及对错误弹窗的优化
 * @param {props} props
 *  @param maxFileSize  Number  文件最大size    默认 100   单位 kb
 *  @param maxLen       Number  最大文件上传数   默认 5
 *  @param extension    Array   支持哪些文件后缀
 *
 * @example
 *  <FileUpload maxFileSize={20} maxLen={3} extension=['.jpg', '.png']></FileUpload>
 */
const FileUpload = ({ value = [], onChange, ...rest }) => {
  const { maxFileSize = 100, maxLen = 5, extension = [] } = rest;
  // 判读是否需要弹出文件检测结果
  let showMessage = true;
  const files = value.map((item, index) => {
    const fileName = item.split("/").pop();
    return {
      uid: index,
      name: fileName,
      status: "done",
      url: item
    };
  });
  console.log("value", value);
  const [fileList, setFileList] = useState(files);
  
  // 拿不到数据??
  console.log("init", fileList);

  // 下面这样能成功渲染
  // const [a, setA] = useState(value);
  // useEffect(
  //   () => {
  //     setFileList(files);
  //     setA(2);
  //   },
  //   [a]
  // );

  const uploadButton = (
    <div>
      <PlusOutlined />
      <div className="ant-upload-text">Upload</div>
    </div>
  );

  // 检测文件是否符合上传规则
  const checkFile = file => {
    const ext = getFileExtendingName(file.name);
    const isExt = extension.indexOf(ext) !== -1;
    if (!isExt) {
      showMessage &&
        message.error({
          onClose() {
            showMessage = true;
          },
          content: "上传文件格式不正确"
        });
      return false;
    }
    // 如果没有 file.size 就认为是之前上传成功过的
    // 就无需再检测了
    const size = file.size ? file.size : 1;
    const isLtSize = size / 1024 < maxFileSize;
    if (!isLtSize) {
      showMessage &&
        message.error({
          onClose() {
            showMessage = true;
          },
          content: "上传的大小超出"
        });
      return false;
    }
    return isExt && isLtSize;
  };

  // eslint-disable-next-line
  const fileOnChange = ({ file, fileList }) => {
    showMessage = false;

    // 为防止文件状态在 uploading done error removed 中都会触发 onchange 事件
    // onchange 中会去检测文件是否符合上传规则, 决定是否执行 setFileList
    // 如果不执行 setFileList 会在 uploading 状态下执行一次就不会执行了, 导致不能监测
    // file 的其他状态。 这里在文件不符合上传规则就不执行 setFileList 是因为 setFileList
    // 会导致一些不符合规则的图片也会在列表中展示
    // https://github.com/ant-design/ant-design/issues/2423
    // https://github.com/ant-design/ant-design/pull/9340
    if (file.status !== "uploading") {
      showMessage = true;
    }
    // 删除和新增成功都需要更新表单上的字段
    if (file.status === "done" || file.status === "removed") {
      // eslint-disable-next-line
      const files = fileList.map(item => {
        if (item.response && item.response.status === "done") {
          return item.response.url;
        }
        return item.url;
      });
      if (!checkFile(file)) {
        return false;
      }
      onChange(files);
    }
    setFileList(fileList);
  };

  // 文件上传前事件
  // 检测文件是否可以被上传
  const beforeUpload = file => {
    return checkFile(file);
  };

  return (
    <div>
      files: {JSON.stringify(fileList)}
      <Upload
        {...rest}
        action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
        listType="picture-card"
        fileList={fileList}
        beforeUpload={beforeUpload}
        onChange={fileOnChange}
      >
        {fileList.length >= maxLen ? null : uploadButton}
      </Upload>
    </div>
  );
};

const Demo = () => {
  const [form] = Form.useForm();
  const onFinish = values => {
    console.log("Received values from form: ", values);
  };

  // setTimeout(() => {
  //   form.setFieldsValue({
  //     files: images,
  //     name: 'abc'
  //   });
  // })
  // form.setFieldsValue({
  //   files: images,
  //   name: 'abc'
  // });

  useEffect(() => {
    // console.log(images)
    form.setFieldsValue({
      files: images,
      name: "abc"
    });
  });

  return (
    <Form layout="inline" form={form} onFinish={onFinish}>
      <Form.Item name="files" label="Price">
        <FileUpload extension={[".jpg", ".png"]} />
      </Form.Item>
      <Form.Item name="name" label="name">
        <Input />
      </Form.Item>
      <Form.Item>
        <Button type="primary" htmlType="submit">
          Submit
        </Button>
      </Form.Item>
    </Form>
  );
};

ReactDOM.render(<Demo />, document.getElementById("container"));

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

凤舞天涯 2022-09-19 02:26:01

useState里只会运行一次, 第一次渲染的时候 value 为空当然是空的
然后你用 form 设置了值 , 但是你的 fileList 并没有对 value 进行响应

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文