Ant Design Pro - Practice React Hooks - Components

demand

Background project, using Ant Design Pro, has such a requirement: there is a table, the width is adaptive, there is a column in the table is notes, the length of the text is variable, we want to use ellipsis when the text is too long, and there is a prompt box to display the full text when the mouse is hovering.

Design

I plan to design a React Hooks component, embedded in the table, to achieve adaptive text ellipsis style.

Cell Width

We can only use relative width for this column, because the whole table is adaptive width. If we use fixed width, it may appear very narrow on the large screen.

Here I use percentages, while maintaining a width state in the page component. After mounted, I calculate the width of this column by percentages and update the status, such as: clientWidth * 0.2. In addition, listen for window resize events and update the width status.

Component width

After column widths are calculated, they are passed to the component through props, and with width, text-overflow: ellipsis can be used to achieve text omission of dynamic widths.

prompt box

This prompt box is available only when it's too long, but not when it's not too long. This is a bit of a hassle, because you need to know if the current state is super-long ellipsis, and we need this state to set whether to add a prompt box or not.

In order to achieve this function, I added two Hooks states: whether they are too long or not, and the true width of the text.

  • Real Width of Text: After rendering, get the width of the element through dom.
  • Overlength: Compare the true width of text with the width of components.

Realization

I'll just paste the code here and look at the key points later.

export default function LineEllipsis(props) {
  const { children, width = '200px', ...restProps } = props;
  const [textWidth, setTextWidth] = useState(0);
  const [isOverflow, setIsOverflow] = useState(false);
  const textRef = useRef(null);
  const textStyles = {
    width,
    display: 'inline-block',
    overflow: 'hidden',
    wordWrap: 'nowrap',
    textOverflow: 'ellipsis',
  };

  useEffect(
    () => {
      if (textRef) {
        const { current } = textRef;
        const clientWidth = current.clientWidth;
        setTextWidth(clientWidth);
        if (!isOverflow && clientWidth > parseInt(width)) {
          setIsOverflow(true);
        } else if (isOverflow && clientWidth < parseInt(width)) {
          setIsOverflow(false);
        }
      }
    },
    [children]
  );

  useEffect(
    () => {
      if (textRef && textWidth > 0) {
        if (!isOverflow && textWidth > parseInt(width)) {
          setIsOverflow(true);
        } else if (isOverflow && textWidth < parseInt(width)) {
          setIsOverflow(false);
        }
      }
    },
    [width]
  );

  const textRender = () => {
    return (
      <span
        ref={textRef}
        style={isOverflow ? textStyles : { display: 'inline-block' }}
        {...restProps}
      >
        {children}
      </span>
    );
  };

  return (
    <div style={{ width }}>
      {isOverflow ? (
        <Popover content={<pre className={styles.pop}>{children}</pre>}>{textRender()}</Popover>
      ) : (
        textRender()
      )}
    </div>
  );
}

Key points:

  • span style, set to inline-block, easy to get the text width.
  • Text may be updated, so you need to monitor the child ren object to update the text width and whether it is too long when it changes.
  • Component widths are dynamically adapted to props parameters, so they also need to be monitored to update whether the state is too long.

summary

The second use of React Hooks did indeed feel the benefits.

  • userEffect's dependency settings are very flexible and easy to use.

    • No settings, each update will trigger.
    • Set to null and trigger only on the first load.
    • Setting to other states, or states in props, triggers only when these states change (* Note that dependencies are not compared in depth when they are objects).
  • Thanks to useState, the usage of useEffect is flexible, and the writing of Hooks components is quite concise.

Tags: Javascript React

Posted on Fri, 09 Aug 2019 00:29:09 -0700 by EcLip$e