Ant Design is a popular design system and a set of React UI components created by Ant Financial, the financial subsidiary of Alibaba Group. It provides a collection of high-quality and customizable components and design patterns for building modern and responsive web applications. Ant Design is widely used in web development, especially for creating user interfaces with a consistent and visually appealing design. It includes components for layout, navigation, forms, data display, and more, making it a valuable resource for developers looking to create user-friendly and aesthetically pleasing web applications. I am very happy that I was able to provide two pull requests for ant-design in this October. In fact, about a year ago or much earlier, I had tried to fork this project, but at that time, I didn't even know what unit tests were. Now, I have finally achieved one of my goals, and I would like to document the process of my pull requests.
This blog post will document the first PR process. I will introduce the second PR process in the following blog post.
Issue
The issue was opened by sefaphlvn. This issue was about the component CheckableTag. It belongs to Tag but works like Checkbox, and user can click it to toggle checked state.
The problem was when using CheckableTag wrapped by Popover component and in Strict Mode, the codes will trigger the findDOMNode method of React, which now is deprecated in StrictMode, and sending warnings:
Debug process
The console log shows about the problem by the CheckableTag:
CheckableTag@https://pwfnyd.csb.app/node_modules/antd/es/tag/CheckableTag.js:22:135
Additionally, the main member of ant-design MadCcc also expressed the same viewpoint:
That's really helpful for me to debug and validate changes. To quickly reproduce, I use the relevant code's logic to replace the project's demo code. Here is my codes (components/tag/demo/checkable.tsx
):
import React, { StrictMode, useState } from 'react';
import { Anchor, Popover, Space, Tag, version } from 'antd';
const { CheckableTag } = Tag;
const App: React.FC = () => {
const tags = ['tag1', 'tag2', 'tag3', 'tag4', 'tag5'];
return (
<StrictMode>
<span style={{ marginRight: 8 }}>Categories:</span>
<Space size={[0, 8]} wrap>
<Anchor
affix={false}
style={{ display: 'block', marginRight: 10 }}
direction="vertical"
items={tags.map((tag, index) => ({
key: index.toString(),
title: (
<div style={{ display: 'flex', alignItems: 'center', width: '100%' }}>
<span
style={{
display: 'flex',
alignItems: 'center',
flex: '1 1 auto',
maxWidth: '100%',
overflow: 'hidden',
textOverflow: 'ellipsis',
}}
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
}}
>
<Popover
content="This field is unchangeable."
title={<div className="warning-popover-title">Info</div>}
>
<CheckableTag
key={tag}
className="ellipsis-tag"
checked={true}
onChange={(checked) => console.log('test')}
>
<span>{tag}</span>
</CheckableTag>
</Popover>
</span>
</div>
),
}))}
></Anchor>
</Space>
</StrictMode>
);
};
export default App;
As expected, when running in local development environment the same error shows:
I then found the code of CheckableTag which is components/tag/CheckableTag.tsx
need to update to support ref. Here I use React.forwardRef
to fix.
Before:
const CheckableTag: React.FC<CheckableTagProps> = (props) => {
const {
prefixCls: customizePrefixCls,
style,
className,
checked,
onChange,
onClick,
...restProps
} = props;
//...
return wrapSSR(
<span
{...restProps}
style={{
...style,
...tag?.style,
}}
className={cls}
onClick={handleClick}
/>,
);
};
After:
const CheckableTag = React.forwardRef<HTMLSpanElement, CheckableTagProps>((props, ref) => {
const {
prefixCls: customizePrefixCls,
style,
className,
checked,
onChange,
onClick,
...restProps
} = props;
//...
return wrapSSR(
<span
{...restProps}
ref={ref}
style={{
...style,
...tag?.style,
}}
className={cls}
onClick={handleClick}
/>,
);
});
More details see the commit
Then I could check again locally and no errors showed as expected.
Reflection
The key to fixing this issue is that I already knew about React.forwardRef
, but now I've forgotten when and how I learned about it. So the insight I've gained is that past learning will eventually come in handy. When I was working on resolving this problem, I also referenced the answers provided by ChatGPT. You can try give ChatGPT the code and ask it how to support refs. I found that ChatGPT would also use React.forwardRef
. If you're not familiar with React.forwardRef
, it's also a good learning opportunity. If you have any questions or thoughts, feel free to leave a comment. Until we meet again, stay curious and stay inspired!
Top comments (0)