React18+ Ant5+ Modal里的 DatePicker & TinyMCE4+ 富文本 解决问题
一个星期又过了,这个坑是表单的坑, 由于我是个新手,表单的坑我还在挖,所以花了几天时间,目前已经解决DatePicker 和 TinyMCE。
目前版本使用:
NodeJS 20.9.0+
package.json:
“react”: “^18.2.0”,
“antd”: “^5.13.1”,
“@tinymce/tinymce-react”: “^4.3.2”,
首先我先来DatePicker:
这里,我使用的来自API 自定rules
DatePicker
// 路径:src/components/newModalArticle.tsx
const modal = (props, ref) => {
const [form] = Form.useForm();
const [rules, setRules] = useState({});
const [fieldID, setFieldID] = useState({});
const [updateField, setUpdateField] = useState('');
useEffect(() => {
// 这里可以自定义 rules 是否有值 (来自API)
if (Object.entries(rules).length > 0) {
const fields = form?.getFieldsError();
let formFields = [];
for (const key in fields) {
formFields.push({
name: fields[key]['name'][0],
errors: [],
});
}
for (let key in formFields) {
Object.entries(rules).forEach(([k, v]) => {
if (k === formFields[key].name) {
if (v) {
formFields[key].errors = [t(v)];
}
return;
}
});
}
// 如有,就发到这里显示
if (formFields.length > 0) {
form.setFields(formFields);
}
}
}, [rules]);
// 开Modal 后,初始化的值
const open = async (row) => {
setOpen(true);
if (props.action === 'edit') {
setFieldID(row.id);
form.setFieldsValue(row);
} else {
form.setFieldsValue({
publishedAt: dayjs(),
});
}
};
// 关闭Modal
const close = () => {
setOpen(false);
setSubmitting(false);
// 这里需重设,否则2次点击时会留下最后一次的记录
form.resetFields();
};
const save = async () => {
setSubmitting(true);
// 这里收集所有表单里的值
const postJSON = form.getFieldsValue();
const response = await general.useFetch(
fieldID ? `/update/article/${fieldID}` : `/insert/article`,
postJSON,
token,
);
if (response && response.code === 200) {
const msg = t('update.success');
setSubmitting(false);
close();
if (props.action === 'new') {
props.onNewSave && props.onNewSave();
} else {
props.onSave && props.onSave();
}
setTimeout(() => {
showNotification({
type: 'success',
msg: msg,
});
}, 20);
} else {
const msg = t('update.error');
setSubmitting(false);
const _formRules = {};
// 这里是表单报错讯息
if (response && response?.errors?.length > 0) {
response.errors.forEach((el) => {
_formRules[el.field] = el.message;
});
}
//_formRules 格式:{ publishedAt: 'Invalid Date' }
setRules(_formRules);
showNotification({
type: 'error',
msg: msg,
});
}
};
return (
<Form.Item
name="publishedAt"
label={
<>
<span className="text-red-500 mr-1">*</span>
{t('announce.publishedAt')}
</>
}
>
<Space direction="vertical" className="w-full">
<DatePicker
showTime
className="w-full"
allowClear={true}
value={
form.getFieldValue('publishedAt')
? dayjs(form.getFieldValue('publishedAt'))
: ''
}
onChange={(date, value) => {
if (value) {
// setUpdateField 再次渲染,让form.getFieldValue('publishedAt') 得到更新
setUpdateField(value);
form.setFieldsValue({
publishedAt: value ?? '',
});
}
}}
/>
</Space>
</Form.Item>
)
export default memo(forwardRef(modal));
TinyMCE
// 路径:src/components/editor/full.tsx
import { Editor } from '@tinymce/tinymce-react';
const full = (props) => {
const updateContent = (e, editor) => {
// 这里是重点,把内容更新到 e.target.value,丢到 props.onChange(e)
editor.on('change input undo redo', () => {
e.target.value = editor.getContent() ?? '';
props.onChange(e);
});
};
return (
<>
<Editor
api-key="apikey"
onInit={updateContent}
initialValue={props?.text}
init={{
height: 500,
toolbar_mode: 'sliding',
plugins:
'anchor autolink charmap codesample emoticons image code link lists media searchreplace table visualblocks wordcount',
toolbar:
'undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | code link custom-upload image media table | align lineheight | numlist bullist indent outdent | emoticons charmap | removeformat',
}}
/>
</>
);
};
export default full;
在页面使用比如以下:
// 路径:pages/article.tsx
const save = async () => {
setSubmitting(true);
// 这样就可以收集 tinymce 的值
const postJSON = form.getFieldsValue();
const response = await general.useFetch(
field.id ? `/update/article/${field.id}` : `/insert/article`,
postJSON,
token,
);
if (response && response.code === 200) {
// 写入逻辑
}
};
return (
<Form.Item
name="content"
label={
<>
<span className="text-red-500 mr-1">*</span>
{t('announce.content')}
</>
}
>
<EditorFull
text={form.getFieldValue('content')}
/>
</Form.Item>
)
这已经是我用最少的代码呈现出来了,我还有很多处理 几乎0 import 导入的东西,都靠vite 和配置到 vite.config.ts 自动帮我导入,让你的代码看起来干净好维护
本作品采用《CC 协议》,转载必须注明作者和本文链接