判断内容为空值的React节点

目标

希望判断一个React节点的value是否是null这种空值,以便替换为符号-

原理

React Element 支持使用 node.props.value的方式获得节点的内容,但是React node有很多类型

React node

要先判断一下再取值,使用React.isValidElement(children)判断是否为React Element。

代码

import * as React from 'react';

export const EMPTY_SYMBOL = '-';

const checkEmpty = (val: any) => (val === undefined || val === null || val === '');

export const noBlankElement = (children: React.ReactNode, blankSymbol: React.ReactNode = EMPTY_SYMBOL): '-' | React.ReactNode => {
  try {
    if (checkEmpty(children)) return blankSymbol;
    if (React.isValidElement(children)) {
      if (checkEmpty(children.props?.value)) {
        const renderType = (children as React.ReactElement)?.type;
        if (typeof renderType === 'function') {
          const element = (renderType as Function)(children);
          if (checkEmpty(element)) return blankSymbol;
          if (element.type === React.Fragment && checkEmpty(children.props.children)) {
            return blankSymbol;
          }
        }
      }
    }
  } catch (e) {
    return children;
  }
  return children;
};

单测:

import * as React from 'react';
import { renderTest, screen } from 'test/lib/helpers/intlTestHelper';
import { noBlankElement, EMPTY_SYMBOL } from 'components/qualityFlow/components/Table/utils/handler';

const testWrapper = (children: React.ReactNode) => renderTest(<>{noBlankElement(children)}</>);

// eslint-disable-next-line react/jsx-no-useless-fragment
const FragmentComponent = () => <>{null}</>;

describe('handler noBlankElement', () => {
  describe('primitives', () => {
    it('check empty string', () => {
      testWrapper('');
      expect(screen.queryByText(EMPTY_SYMBOL)).toBeInTheDocument();
    });

    it('check null', () => {
      testWrapper(null);
      expect(screen.queryByText(EMPTY_SYMBOL)).toBeInTheDocument();
    });

    it('check undefined', () => {
      testWrapper(undefined);
      expect(screen.queryByText(EMPTY_SYMBOL)).toBeInTheDocument();
    });

    it('check number 0', () => {
      testWrapper(0);
      expect(screen.queryByText(EMPTY_SYMBOL)).not.toBeInTheDocument();
    });

    it('check false', () => {
      testWrapper(false);
      expect(screen.queryByText(EMPTY_SYMBOL)).not.toBeInTheDocument();
    });
  });

  describe('ReactElement', () => {
    it('render empty React.Fragment', () => {
      testWrapper(<FragmentComponent />);
      expect(screen.queryByText(EMPTY_SYMBOL)).toBeInTheDocument();
    });

    it('render element directly', () => {
      testWrapper(<div />);
      expect(screen.queryByText(EMPTY_SYMBOL)).not.toBeInTheDocument();
    });
  });
});

Reference:
https://beta.reactjs.org/reference/react/isValidElement
https://stackoverflow.com/questions/29568721/getting-dom-node-from-react-child-element

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容