Best Practices for Ant Design Forms, Dynamic Form Handling, and Component Organization in React
This article reviews practical guidelines for building maintainable Ant Design forms in React, covering layout strategies, dynamic form techniques, component encapsulation, table and tab implementations, CSS styling conventions, architecture considerations, and custom hooks to improve code quality and developer productivity.
The author reflects on the challenges of maintaining a large React codebase that heavily uses Ant Design components, especially forms, and shares a series of practical recommendations to make the code more readable, reusable, and easier to maintain.
Form Layout and Basic Tips
Use <Form> with labelCol and wrapperCol for responsive layout; choose horizontal , vertical , or inline layout modes, noting that inline sets the outermost display to flex . Remove unnecessary className and div wrappers, and configure required fields via rules on Form.Item .
Dynamic Form Patterns
When a form field needs to map a different prop name, configure valuePropName or trigger . Avoid attaching onChange directly to child components unless you need custom state handling; instead rely on Form.useWatch , dependencies , or shouldUpdate for simple dynamic behavior. For complex scenarios, consider Form.List or libraries like @formily/react .
Component Encapsulation
Encapsulate reusable UI pieces (e.g., a house‑selection component) without wrapping Form.Item inside the component, so the parent form retains full control over validation and value propagation. Example:
return (
<Form.Item label="房号" name="houseId" {...props} rules={[{ required, message: '请输入' }]}>
<div className="flex" style={{ display: 'flex' }}>
<Form.Item noStyle name="number">
<Select ...>{HouseUser.map(item => <Option key={item.number}>{item.number}</Option>)}</Select>
</Form.Item>
...
</div>
</Form.Item>
);Table Column Optimization
Extract static option lists to separate modules and use a utility function for rendering, reducing repetitive switch logic. Bad example shows inline render with many ternary checks; good example imports a pre‑defined option array and a helper getText function.
export const payTypeOption = [{ label: '微信', value: 'WEIXIN' }, ...];
const getText = val => payTypeOption.find(item => item.value === val)?.label || '-';
<Form.Item label="支付方式" name="payType">
<Select option={payTypeOption} allowClear placeholder="请选择" size="large" />
</Form.Item>
// column definition
{ title: '支付方式', dataIndex: 'wayOfInOutType', render: (text, record) => getText(text) }Tabs Implementation
Prefer Ant Design's built‑in Tabs component instead of hand‑rolling tab logic. When custom state is needed, store the active key in a state variable and render the corresponding component conditionally.
const PropertyArchives = () => {
const [activeKey, setActiveKey] = useState(1);
const tabs = [{ id: 1, name: 'xxx1' }, { id: 2, name: 'xxx2' }];
return (
<Wrap>
<div className="tabber">
{tabs.map(v => (
<div key={v.id} onClick={() => setActiveKey(v.id)} className={v.id===activeKey ? 'tabberClickList' : 'tabberList'}>{v.name}</div>
))}
</div>
{activeKey === 1 ? <WYArchives /> : <CategorySettings />}
</Wrap>
);
};CSS Styling Guidelines
Leverage Ant Design's layout components ( Row , Col , Space , Divider , Descriptions , Typography ) instead of writing custom CSS whenever possible. Keep custom styles minimal and avoid overriding component defaults unless absolutely necessary.
Architecture and State Management
Avoid building a custom scaffolding framework when a mature solution like Umi or Create‑React‑App already exists. Use centralized state management (e.g., Redux) for values that need to be shared across many layers, and pass data via history.push when navigating between pages.
Custom Hook for Pagination
Replace repetitive pagination logic with a reusable hook. Bad example mixes many useState variables and manual flag handling; good example abstracts the logic into usePageData which returns content , getNextPageData , isLoad , and loading .
import { usePageData } from '@/utils/hooks';
const Index = () => {
const { content, getNextPageData, isLoad, loading } = usePageData({ api: xxx, initParams: xxx });
const onScrollToLower = () => getNextPageData();
return (/* render list */);
};Final Thoughts
The author encourages developers to prioritize maintainability and practicality over overly clever or “elegant” code, to share clean examples with the community, and to continuously refactor legacy code for better readability and future extensibility.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.