The React ecosystem has a vast amount of components and libraries that you can use to easily build web applications. The Ant Design library is one of those which provides a great range of ready to go React components, complete with styling for the whole site.
React生态系统具有大量的组件和库,您可以使用它们轻松地构建Web应用程序。 Ant Design库是其中之一,它提供了很多现成的React组件,并为整个站点提供了样式。
In this article, we’ll look into how we can build a custom input to interact with the Ant Design Form component, and add a 3rd party component in order to provide greater functionality.
在本文中,我们将研究如何构建自定义输入以与Ant Design Form组件进行交互,并添加第3方组件以提供更大的功能。
建立 (Setup)
Let’s start by cloning the baseline (https://github.com/chilledoj/antd-custom-form-app) repo and installing the dependencies with Yarn.
让我们首先克隆基线( https://github.com/chilledoj/antd-custom-form-app )回购并使用Yarn安装依赖项。
git clone [email protected]:chilledoj/antd-custom-form-app.gitcd antd-custom-form-appyarn
You should now be able to run the app with yarn start which will open localhost:1234
in your browser.
现在,您应该能够使用yarn start运行应用程序,它将在浏览器中打开localhost:1234
。
You can enter a username into the form and the JSON object of the form values is displayed.
您可以在表单中输入用户名,并显示表单值的JSON对象。
Form values received and displayed 表单值已接收并显示背景 (Background)
App / index.tsx (App/index.tsx)
The App component is the main container for the form component. Rather than use a router, we are just using a null check on the state within the App component to decide whether to display the form or the results of the form. We also pass in some handlers to set and clear the results. The onSubmit
handler could also have included an async request to an API and/or dispatch to a redux store.
App组件是表单组件的主要容器。 而不是使用路由器,我们只是对App组件内的状态使用空检查来决定是显示表单还是显示表单结果。 我们还传入一些处理程序来设置和清除结果。 onSubmit
处理程序还可能包括对API的异步请求和/或分派给Redux存储。
const App: FC = () => {
const [vals, setVals] = useState(null); const onSubmit = (values: unknown): void => {
setVals(values);
}; const clearValues = (): void => {
setVals(null);
}; ... return ( ... {vals === null ? (
) : (
)}
);
};
We could have written a type for the state, but we’ll ignore that for the time being.
我们可以为状态编写一个类型,但是暂时将其忽略。
组件/Form.tsx (components/Form.tsx)
As per the Ant Design docs, we first set up a Form ref with the useForm
hook and ensure it is passed into the form component. We create a wrapper handler onFinish
that will run when the form is submitted and will extract the actual form values from the form component and pass these onto the onSubmit
handler. Each form item is wrapped in the Form.Item
container.
根据Ant Design文档,我们首先使用useForm
钩子设置Form ref,并确保将其传递到form组件中。 我们创建了一个包装处理程序onFinish
,该处理程序将在提交表单时运行,并将从表单组件中提取实际的表单值,并将其传递给onSubmit
处理程序。 每个表单项都包装在Form.Item
容器中。
const TestForm: FC = ({ onSubmit }: TestFormProps) => {
const [form] = Form.useForm();
const onFinish = (): void => {
onSubmit(form.getFieldsValue());
}; return (
);
};
自定义组件 (A Custom Component)
Create a new file in the components directory called MyInput.tsx
. In this, we will create a simple HTML input element that is controlled by the Antd form.
在组件目录中创建一个名为MyInput.tsx
的新文件。 在此,我们将创建一个由Antd表单控制的简单HTML输入元素。
The docs state that for an element to be controlled correctly within the form, the component must have a value
and onChange
prop.
文档指出,要在表单中正确控制元素,组件必须具有value
和onChange
属性。
Let’s create our component.
让我们创建我们的组件。
import React, {FC} from 'react';
const styles = {
wrapper: {
display: "block",
width: "100%"
},
input: {
fontFamily: "monospace",
display: "block",
width: "100%"
}
};interface OnChangeHandler {
(e): void;
}interface MyInputProps {
value: number;
onChange: OnChangeHandler;
}const MyInput: FC = ({value, onChange}: MyInputProps) => {
return (
);
}
export default MyInput;
And now let’s use this component within the Form. Edit Form.tsx
to include our new component.
现在,让我们在表单中使用此组件。 编辑Form.tsx
以包括我们的新组件。
...return (
{/* @ts-ignore */}
N.B. the {/* @ts-ignore */}
bit just tells typescript linters to ignore the fact that we are not explicitly setting the required props of the component. The Form.Item
component will take care of passing those in from the form for us.
注意, {/* @ts-ignore */}
位只是告诉打字机短毛绒忽略了我们没有明确设置组件所需道具的事实。 Form.Item
组件将负责将表单中的内容传递给我们。
You should now see our number input in the form and submitting shows that the form component is receiving the value of the input correctly.
现在,您应该在表单中看到我们的数字输入,并且提交显示表单组件正在正确接收输入的值。
Custom number input within Antd form 在Antd表单中输入自定义号码内部状态 (Internal State)
Our component might need to handle the internal state to provide richer functionality and have a separate handler for the onChange
event.
我们的组件可能需要处理内部状态以提供更丰富的功能,并为onChange
事件提供单独的处理程序。
We can easily create a custom trigger, that then sends the relevant data back out to the parent Form.Item
through the onChange
handler.
我们可以轻松地创建一个自定义触发器,然后通过onChange
处理程序将相关数据发送回父Form.Item
。
Let’s do something a little funky. We’ll create an interval callback that increases the number input periodically.
让我们做一些时髦的事情。 我们将创建一个间隔回调,以定期增加输入的数量。
Install the ahooks library with yarn add ahooks
. We can then update our input to use the useInterval
hook within the library.
使用yarn add ahooks
安装ahooks库。 然后,我们可以更新输入以使用库中的useInterval
挂钩。
import React, { FC, useState } from 'react';
import { useInterval } from 'ahooks';
...
type OnChangeHandler = (num: number) => void;interface MyInputProps {
value: number;
onChange: OnChangeHandler;
}const MyInput: FC = ({ value, onChange }: MyInputProps) => {
const [val, setVal] = useState(value || 0);
useInterval(() => {
setVal(Number(val || 0) + 1);
onChange(Number(val || 0) + 1);
}, 2500);
const mdlChange = (e: React.ChangeEvent): void => {
setVal(Number(e.target.value));
onChange(Number(e.target.value));
}; return (
);
};export default MyInput;
Within the interval callback, we set both the internal state (which is used by the input element) and send the same back through the onChange
handler.
在时间间隔回调中,我们既设置了内部状态(由输入元素使用), onChange
通过onChange
处理程序发送回去。
We create a separate handler for the onChange
of the input element called mdlChange
which can then also set the internal state and update the parent form element.
我们为输入元素的onChange
创建了一个单独的处理程序,称为mdlChange
,该处理程序还可以设置内部状态并更新父表单元素。
第三方图书馆 (Third-Party Libraries)
We may want to integrate other third-party libraries that have their own way of dealing with the state of the component and notifying changes. Most should adhere to the same standard though whereby the value
and onChange
props are provided.
我们可能希望集成其他第三方库,它们具有处理组件状态和通知更改的方式。 尽管大多数提供的value
和onChange
道具都应遵循相同的标准。
If the component decides to have a different way of providing the underlying data value, then the Form.Item
Antd component has the getValueProps
property which tells the form how to extract out the value to provide to the Form from the returned data.
如果组件决定采用其他方式提供基础数据值,则Form.Item
Antd组件具有getValueProps
属性,该属性告诉表单如何从返回的数据中提取要提供给Form的值。
The React Markdown Editor Lite (https://www.npmjs.com/package/react-markdown-editor-lite) has both the value and onChange properties. However, the data returned back from the component is an object with both the underlying markdown text and the rendered html along with the change event from the underlying textarea.
React Markdown编辑器精简版( https://www.npmjs.com/package/react-markdown-editor-lite )具有value和onChange属性。 但是,从组件返回的数据是一个具有基础markdown文本和呈现的html以及基础textarea的change事件的对象。
/// https://github.com/HarryChen0506/react-markdown-editor-lite/blob/master/src/editor/index.tsx...interface EditorProps extends EditorConfig {
...
value?: string;
onChange?: (
data: {
text: string;
html: string;
},
event?: React.ChangeEvent,
) => void;
...
}
Install this library and markdown-it
which is required to render the markdown to html.
安装此库和markdown-it
,这是将markdown呈现为html所必需的。
yarn add react-markdown-editor-lite markdown-it
Now let’s look to add this into the Form component.
现在,让我们将其添加到Form组件中。
/// components/Form.tsx...
import MarkdownIt from 'markdown-it';
import MdEditor from 'react-markdown-editor-lite';
import 'react-markdown-editor-lite/lib/index.css';
...// Initialize a markdown parser
const mdParser = new MarkdownIt({
html: false,
linkify: true,
typographer: true,
});
Now when we go to add the editor within a Form.Item
, we just need to tell that component how to extract the value we need, from the data
object sent from the markdown editor.
现在,当我们在Form.Item
添加编辑器时,我们只需要告诉该组件如何从markdown编辑器发送的data
对象中提取所需的值即可。
name="description"
label="Full Description"
getValueFromEvent={(data): string => data.text} // extract the value from the data object
>
style={{ height: '500px' }}
renderHTML={(text): string => mdParser.render(text)}
/>
摘要 (Summary)
There are so many UI component libraries for React that provide the building blocks for most apps. The Ant Design library comes with some fantastic components, but there could always be a need to adapt or add custom components. The extensible configuration options provide the ability to do this very easily, and with the addition of Typescript, it becomes easier to peek at what the expected value types from third-party libraries should be.
React有许多UI组件库,它们为大多数应用程序提供了构建块。 Ant Design库带有一些出色的组件,但是始终可能需要调整或添加自定义组件。 可扩展的配置选项提供了非常容易执行此操作的能力,并且通过添加Typescript,可以更轻松地查看第三方库的期望值类型。
翻译自: https://medium.com/swlh/use-custom-and-third-party-react-form-components-with-ant-design-and-typescript-2732e7849aee