使用 useState hook 初始化值不能生效?
在自定义表单控件中。接受从表单中传过来的值,修改后赋给 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
useState里只会运行一次, 第一次渲染的时候 value 为空当然是空的
然后你用 form 设置了值 , 但是你的 fileList 并没有对 value 进行响应