Ref大補帖

  • Ref v.s. render
  • Ref 與 class的搭配使用
  • mutation observer

Hooks update

Hooks v.s. Ref

NTCH Popup

const popup = useMemo(() => {
    if (!isShown) return null;

    const wrapperElem = wrapperRef.current;

    if (!wrapperElem) return null;

    const Component = component;

    const { height } = wrapperElem.getBoundingClientRect();

    const popupWrapperStyles = [
      styles.popup,
    ];

    switch (activedPosition) {
      case Positions.LEFT_TOP:
        popupWrapperStyles.push({
          right: 0,
          bottom: `${height + 8}px`,
          left: 'auto',
          top: 'auto',
        });
        popupWrapperStyles.push(styles.popupTriangleLeftTop);
        break;

      case Positions.LEFT_BOTTOM:
        popupWrapperStyles.push({
          right: 0,
          top: `${height + 8}px`,
          left: 'auto',
          bottom: 'auto',
        });
        popupWrapperStyles.push(styles.popupTriangleLeftBottom);
        break;

      case Positions.RIGHT_TOP:
        popupWrapperStyles.push({
          right: 'auto',
          bottom: `${height + 8}px`,
          left: 0,
          top: 'auto',
        });
        popupWrapperStyles.push(styles.popupTriangleRightTop);
        break;

      case Positions.RIGHT_BOTTOM:
      default:
        popupWrapperStyles.push({
          right: 'auto',
          top: `${height + 8}px`,
          left: 0,
          bottom: 'auto',
        });
        popupWrapperStyles.push(styles.popupTriangleRightBottom);
        break;
    }

    return (
      <div css={popupWrapperStyles}>
        <Component />
      </div>
    );
  }, [isShown, component, activedPosition]);

Class

Animation & Ref

Example again

Mutation Observer

前情提要:

: triggers

拆分邏輯以達成關注點分離:提高可讀性

MDN對mutation observer的介紹:

The MutationObserver interface provides the ability to watch for changes being made to the DOM tree.

Constructor

new MutationObserver(
  function callback
);

Instance method

void observe( Node target, MutationObserverInit options );
void disconnect();
Array takeRecords();
useEffect(() => {
    const { current: button } = blockButtonRef;

    if (!button) return () => {};

    function onObserveHandler(mutations) {
      const classList = Array.from(mutations[0].target.classList);

      const isHoveredClassAdded = classList.some(className => className === 'hovered');

      if (isHoveredClassAdded) {
        setInfoModalOpened(true);
      } else {
        setInfoModalOpened(false);
      }
    }

    const buttonObserver = new MutationObserver(onObserveHandler);

    buttonObserver.observe(button, {
      attributeOldValue: true,
      attributes: true,
    });

    return () => {
      buttonObserver.disconnect();
    };
  }, []);

謝謝大家

Ref

By ian Lai

Ref

  • 369