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 协议》,转载必须注明作者和本文链接
全栈程序员(Blockchain, Web3, Nuxt3+, vue3+, React18+, PHP, MySQL, HTML, CSS, JavaScrIpt/JQuery)
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!