DEV Community

Mingming Ma
Mingming Ma

Posted on • Edited on

My PRs to ant-design: PR1

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.
CheckableTag

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:
issuelog

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
Enter fullscreen mode Exit fullscreen mode

Additionally, the main member of ant-design MadCcc also expressed the same viewpoint:

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;

Enter fullscreen mode Exit fullscreen mode

As expected, when running in local development environment the same error shows:
demo

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}
    />,
  );
};
Enter fullscreen mode Exit fullscreen mode

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}
    />,
  );
});

Enter fullscreen mode Exit fullscreen mode

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)