react#useLayoutEffect TypeScript Examples

The following examples show how to use react#useLayoutEffect. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: InlineDatePicker.tsx    From ant-extensions with MIT License 7 votes vote down vote up
InlineDatePicker: React.FC<DatePickerProps> = React.forwardRef<
  React.Component,
  DatePickerProps
>((props, ref) => {
  const refContainer = useRef<HTMLDivElement>(null);
  const refPicker = useRef<HTMLDivElement>(document.createElement("div"));

  useLayoutEffect(() => {
    if (refContainer.current) {
      refContainer.current.appendChild(refPicker.current);
    }
  }, []);

  return (
    <I18nextProvider i18n={i18next}>
      <div ref={refContainer} className="ant-ext-sd__inlinePicker">
        <DatePicker
          {...props}
          ref={ref}
          open
          inputReadOnly
          getPopupContainer={() => refPicker.current}
        />
      </div>
    </I18nextProvider>
  );
})
Example #2
Source File: utils.ts    From erda-ui with GNU Affero General Public License v3.0 7 votes vote down vote up
export function useSmartTooltip({ mouseX, mouseY }: { mouseX: number; mouseY: number }) {
  const ref = useRef<HTMLDivElement>(null);
  useLayoutEffect(() => {
    const element = ref.current;
    if (element != null) {
      if (mouseY + TOOLTIP_OFFSET + element?.offsetHeight >= window.innerHeight) {
        if (mouseY - TOOLTIP_OFFSET - element.offsetHeight > 0) {
          element.style.top = `${mouseY - element.offsetHeight - TOOLTIP_OFFSET}px`;
        } else {
          element.style.top = '0px';
        }
      } else {
        element.style.top = `${mouseY + TOOLTIP_OFFSET}px`;
      }

      if (mouseX + TOOLTIP_OFFSET + element.offsetWidth >= window.innerWidth) {
        if (mouseX - TOOLTIP_OFFSET - element.offsetWidth > 0) {
          element.style.left = `${mouseX - element.offsetWidth - TOOLTIP_OFFSET}px`;
        } else {
          element.style.left = '0px';
        }
      } else {
        element.style.left = `${mouseX + TOOLTIP_OFFSET}px`;
      }
    }
  });

  return ref;
}
Example #3
Source File: useWindowSize.tsx    From firecms with MIT License 6 votes vote down vote up
export function useWindowSize(): WindowSize {
    const [size, setSize] = useState<WindowSize>({ width: 0, height: 0 });
    useLayoutEffect(() => {
        function updateSize() {
            setSize({ width: window.innerWidth, height: window.innerHeight });
        }

        window.addEventListener("resize", updateSize);
        updateSize();
        return () => window.removeEventListener("resize", updateSize);
    }, []);
    return size;
}
Example #4
Source File: XarrowV2.stories.tsx    From react-xarrows with MIT License 6 votes vote down vote up
useParseProps = (props: MyComponentPropsType) => {
  const [parsedVals, setParsedVals] = useState({ parsedProp1: parseVal1(MyComponentDefaultProps.prop1) });

  useLayoutEffect(() => {
    parsedVals.parsedProp1 = parseVal1(props.prop1);
    setParsedVals({ ...parsedVals });
  }, [props.prop1]);

  return parsedVals;
}
Example #5
Source File: checkboxColumn.tsx    From react-datasheet-grid with MIT License 6 votes vote down vote up
CheckboxComponent = React.memo<CellProps<boolean, any>>(
  ({ focus, rowData, setRowData, active, stopEditing }) => {
    const ref = useRef<HTMLInputElement>(null)

    // When cell becomes focus we immediately toggle the checkbox and blur the cell by calling `stopEditing`
    // Notice the `nextRow: false` to make sure the active cell does not go to the cell below and stays on this cell
    // This way the user can keep pressing Enter to toggle the checkbox on and off multiple times
    useLayoutEffect(() => {
      if (focus) {
        setRowData(!rowData)
        stopEditing({ nextRow: false })
      }
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [focus, stopEditing])

    return (
      <input
        className="dsg-checkbox"
        // Important to prevent any undesired "tabbing"
        tabIndex={-1}
        type="checkbox"
        ref={ref}
        checked={Boolean(rowData)}
        // When cell is not active, we allow the user to toggle the checkbox by clicking on it
        // When cell becomes active, we disable this feature and rely on focus instead (see `useLayoutEffect` above)
        onMouseDown={() => !active && setRowData(!rowData)}
        onChange={() => null}
      />
    )
  }
)
Example #6
Source File: Tag.tsx    From frontend with GNU General Public License v3.0 6 votes vote down vote up
Tag = ({ children, bgColor, fontColor, getWidth, ...props }: IProps): JSX.Element => {
  const elementsRef = useRef<HTMLDivElement>(null);
  const getWidthAfterDOMLoad = useCallback(() => {
    getWidth(elementsRef.current?.getBoundingClientRect().width || 0);
  }, [getWidth]);

  useLayoutEffect(() => {
    window.addEventListener('load', getWidthAfterDOMLoad);
  }, [getWidthAfterDOMLoad]);
  return (
    <TagElement ref={elementsRef} bgColor={bgColor} fontColor={fontColor} {...props}>
      {children}
    </TagElement>
  );
}
Example #7
Source File: useWindowSize.ts    From taskcafe with MIT License 6 votes vote down vote up
export default function useWindowSize() {
  const [size, setSize] = useState([0, 0]);
  useLayoutEffect(() => {
    function updateSize() {
      setSize([window.innerWidth, window.innerHeight]);
    }
    window.addEventListener('resize', updateSize);
    updateSize();
    return () => window.removeEventListener('resize', updateSize);
  }, []);
  return size;
}
Example #8
Source File: Glider.tsx    From atlas with GNU General Public License v3.0 6 votes vote down vote up
function useEventListener<K extends keyof GliderEventMap>(
  element: HTMLElement | undefined | null,
  event: K,
  // eslint-disable-next-line @typescript-eslint/no-empty-function
  listener: (event: GliderEvent<GliderEventMap[K]>) => void = () => {}
) {
  const savedListener = useRef(listener)

  useEffect(() => {
    savedListener.current = listener
  }, [listener])

  useLayoutEffect(() => {
    if (!element) {
      return
    }
    element.addEventListener(event, savedListener.current)
    return () => {
      element.removeEventListener(event, savedListener.current)
    }
  }, [event, element])
}
Example #9
Source File: VirtualTableHeader.tsx    From posthog-foss with MIT License 6 votes vote down vote up
function VirtualTableHeader<RecordType>({
    columns,
    handleResize,
    layoutEffect,
    minColumnWidth: defaultMinColumnWidth,
    expandable,
}: VirtualTableHeaderProps<RecordType>): JSX.Element {
    const height = 60
    useLayoutEffect(() => (typeof layoutEffect === 'function' ? layoutEffect() : undefined))
    return (
        <div className="resizable-virtual-table-header">
            {!!expandable && (
                <div className="left-spacer" style={{ width: expandable?.columnWidth || ANTD_EXPAND_BUTTON_WIDTH }} />
            )}
            {columns.map(({ title, width, widthConstraints }, index) => {
                const minColumnWidth = widthConstraints?.length ? widthConstraints[0] : defaultMinColumnWidth
                const maxColumnWidth = widthConstraints?.length ? widthConstraints[1] : Infinity
                return (
                    <ResizableTitle
                        key={index}
                        initialWidth={width ?? minColumnWidth}
                        height={height}
                        onResize={handleResize(index)}
                        minConstraints={[minColumnWidth, height]}
                        maxConstraints={[maxColumnWidth, height]}
                    >
                        {title}
                    </ResizableTitle>
                )
            })}
        </div>
    )
}
Example #10
Source File: index.ts    From react-carousel with MIT License 6 votes vote down vote up
useWindowWidthChange = (callBack: (changed: number) => any) => {
	const [windowWidth, setWindowWidth] = useState(getWindowWidth());
	useLayoutEffect(() => {
		const update = () => {
			const changed = windowWidth - window.innerWidth;
			setWindowWidth(window.innerWidth);
			callBack(changed);
		};
		window.addEventListener('resize', update);
		return () => window.removeEventListener('resize', update);
	}, []);
	return;
}
Example #11
Source File: useColor.ts    From sybil-interface with GNU General Public License v3.0 6 votes vote down vote up
export function useColor(token?: Token) {
  const [color, setColor] = useState('#2172E5')

  useLayoutEffect(() => {
    let stale = false

    if (token) {
      getColorFromToken(token).then((tokenColor) => {
        if (!stale && tokenColor !== null) {
          setColor(tokenColor)
        }
      })
    }

    return () => {
      stale = true
      setColor('#2172E5')
    }
  }, [token])

  return color
}
Example #12
Source File: Aside.tsx    From ant-extensions with MIT License 6 votes vote down vote up
Aside: React.FC = React.memo(() => {
  const { t } = useTranslation(I18nKey);
  const { selected, editConfig } = useContext(Context);

  const [active, setActive] = useState<string | string[]>(["widgets"]);

  useLayoutEffect(() => {
    setActive(selected ? ["config", "widgets"] : ["widgets"]);
  }, [selected]);

  return (
    <div className="ant-ext-pm__aside">
      <Collapse activeKey={active}>
        {selected && (
          <Collapse.Panel
            key="config"
            showArrow={false}
            header={t("label.config")}
            extra={<CloseOutlined onClick={() => editConfig(undefined)} />}
          >
            <Config />
          </Collapse.Panel>
        )}
        <Collapse.Panel showArrow={false} key="widgets" header={t("label.widgets")}>
          <WidgetList />
        </Collapse.Panel>
      </Collapse>
    </div>
  );
})
Example #13
Source File: ColorPicker.tsx    From animation-editor with MIT License 6 votes vote down vote up
Strip: React.FC<{ hue: number; onHueChange: (hue: number) => void }> = (props) => {
	const canvas = useRef<HTMLCanvasElement>(null);
	const ctx = useRef<CanvasRenderingContext2D | null>(null);
	const [y, setY] = useState(() => Math.round((props.hue / 360) * HEIGHT));

	useLayoutEffect(() => {
		ctx.current = canvas.current?.getContext("2d") || null;
	}, [canvas.current]);

	// Render strip once on mount
	useLayoutEffect(() => {
		if (!ctx.current) {
			return;
		}

		for (let i = 0; i < HEIGHT; i += 1) {
			ctx.current.fillStyle = `hsl(${(i / HEIGHT) * 360}, 100%, 50%)`;
			ctx.current.fillRect(0, i, STRIP_WIDTH, 1);
		}
	}, [ctx.current]);

	const pixelSelector = useCanvasPixelSelector(
		canvas,
		{ allowOutside: true },
		(rgbColor, position) => {
			const [hue] = rgbToHSL(rgbColor);
			props.onHueChange(hue);
			setY(position.y);
		},
	);

	return (
		<div style={{ position: "relative", marginRight: 16 }}>
			<canvas ref={canvas} height={HEIGHT} width={STRIP_WIDTH} {...pixelSelector} />
			<div style={{ top: y }} className={s("hueCursor")} />
		</div>
	);
}
Example #14
Source File: index.ts    From ChatUI with MIT License 6 votes vote down vote up
Portal: React.FC<PortalProps> = (props) => {
  const { children, container = document.body, onRendered } = props;
  const [mountNode, setMountNode] = useState<Element | null>(null);

  useEffect(() => {
    setMountNode(getEl(container));
  }, [container]);

  useLayoutEffect(() => {
    if (onRendered && mountNode) {
      onRendered();
    }
  }, [mountNode, onRendered]);

  return mountNode ? createPortal(children, mountNode) : mountNode;
}
Example #15
Source File: useOverflowWrapper.ts    From hub with Apache License 2.0 6 votes vote down vote up
useOverflowWrapper = (
  wrapperRef: MutableRefObject<HTMLDivElement | null>,
  maxHeight: number,
  itemsLength: number
) => {
  const getHeight = (): number => {
    if (wrapperRef && wrapperRef.current) {
      return wrapperRef.current.offsetHeight;
    } else {
      return 0;
    }
  };

  const checkDimensions = () => {
    const height = getHeight();
    return height > maxHeight;
  };

  const [overflowContainer, setOverflowContainer] = useState<boolean>(() => checkDimensions());

  const handleOverflow = () => {
    setOverflowContainer(checkDimensions());
  };

  useEffect(() => {
    window.addEventListener('resize', throttle(handleOverflow, 200));
    return () => window.removeEventListener('resize', handleOverflow);
  }, []); /* eslint-disable-line react-hooks/exhaustive-deps */

  useLayoutEffect(() => {
    handleOverflow();
  }, []); /* eslint-disable-line react-hooks/exhaustive-deps */

  useEffect(() => {
    handleOverflow();
  }, [itemsLength]); /* eslint-disable-line react-hooks/exhaustive-deps */

  return overflowContainer;
}
Example #16
Source File: render.tsx    From react-loosely-lazy with Apache License 2.0 6 votes vote down vote up
usePlaceholderRender = (resolveId: string, content: HTMLElement[]) => {
  const hydrationRef = useRef<HTMLInputElement | null>(null);
  const { current: ssrDomNodes } = useRef(content || ([] as HTMLElement[]));

  useLayoutEffect(() => {
    const element = hydrationRef.current;
    const { parentNode } = element || {};

    if (parentNode && !parentNode.contains(ssrDomNodes[0])) {
      ssrDomNodes.reverse().forEach((node: HTMLElement) => {
        // this fixes an issue with Chrome that re-triggers and cancels prefetch
        // when node is appended again, making network panel quite noisy
        if (isLinkPrefetch(node)) node.rel = '';

        parentNode.insertBefore(node, (element as any).nextSibling);
      });
    }

    return () => {
      ssrDomNodes.forEach((node: HTMLElement) =>
        node.parentNode?.removeChild(node)
      );
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [hydrationRef.current, ssrDomNodes]);

  return hydrationRef;
}
Example #17
Source File: Hits.tsx    From checklist with MIT License 6 votes vote down vote up
Hits: FC<Props & HitsProvided<ChecklistHit>> = ({ hits, onClick }) => {
  const enterListener = (event: KeyboardEvent) => {
    if (event.key === 'Enter' && hits.length > 0) {
      navigate(`/checklist/${hits[0].slug}`);
    }
  };

  useLayoutEffect(() => {
    window.addEventListener('keyup', enterListener);

    return () => {
      window.removeEventListener('keyup', enterListener);
    };
  });

  return (
    <div className="c-search__hits">
      {hits.map(hit => (
        <SearchCard
          key={hit.objectID}
          category={hit.category}
          categorySlug={hit.categorySlug}
          todoCount={hit.todoCount}
          title={hit.title}
          description={hit.description}
          tags={hit.tags}
          slug={hit.slug}
          onClick={onClick}
        />
      ))}
    </div>
  );
}
Example #18
Source File: useDynamicFontSize.tsx    From amazon-chime-live-events with Apache License 2.0 6 votes vote down vote up
useDynamicFontSize = (ref: RefObject<HTMLElement>) => {
  const [fontSize, setFontSize] = useState<string>();

  useLayoutEffect(() => {
    if (!ref.current) {
      return;
    }

    const { width } = ref.current.getBoundingClientRect();
    setFontSize(getNamePlateFontSize(width));
  }, []);

  useEffect(() => {
    const el = ref.current;

    if (!el) {
      return;
    }

    const handleResize = debounce(50, (entries: any) => {
      const { width } = entries[0].contentRect;
      setFontSize(getNamePlateFontSize(width));
    });

    const resizeObserver = new ResizeObserver(handleResize);
    resizeObserver.observe(el);

    return () => resizeObserver.unobserve(el);
  }, []);

  return fontSize;
}
Example #19
Source File: useElementAspectRatio.tsx    From amazon-chime-sdk-smart-video-sending-demo with Apache License 2.0 6 votes vote down vote up
useElementAspectRatio = (ref: RefObject<HTMLElement>): AspectRatio | null => {
  const [ratio, setRatio] = useState<AspectRatio | null>(null);

  useLayoutEffect(() => {
    if (!ref.current) {
      return;
    }

    const { height, width } = ref.current.getBoundingClientRect();
    setRatio(getAspectRatio(height, width));
  }, []);

  useEffect(() => {
    if (!ref.current) {
      return;
    }

    const handleResize = debounce(50, (entries: any) => {
      const { height, width } = entries[0].contentRect;
      setRatio(getAspectRatio(height, width));
    });

    const resizeObserver = new ResizeObserver(handleResize);
    resizeObserver.observe(ref.current);

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

  return ratio;
}
Example #20
Source File: use-initial.test.tsx    From use-between with MIT License 6 votes vote down vote up
test('Should block effect hooks on server', () => {
  const fn = jest.fn()
  const fnA = jest.fn()
  const fnB = jest.fn()
  const fnC = jest.fn()
  const useStore = () => {
    useEffect(fnA, [])
    useLayoutEffect(fnB, [])
    useImperativeHandle(fnC, () => 10, [])
    fn()
  }

  const A = () => {
    useBetween(useStore)
    return null
  }
  const B = () => {
    useBetween(useStore)
    return null
  }
  const C = () => {
    useInitial(null, true)
    return <><A /><B /></>
  }

  mount(<C/>)
  expect(fn).toBeCalledTimes(1)
  expect(fnA).toBeCalledTimes(0)
  expect(fnB).toBeCalledTimes(0)
  expect(fnC).toBeCalledTimes(0)
});
Example #21
Source File: useCombineRef.ts    From fe-foundation with Apache License 2.0 6 votes vote down vote up
export function useCombineRef<T>(...refs: Array<Ref<T> | undefined>): RefObject<T> {

    const ref = useRef<T>(null);

    // 每一次useLayoutEffect都同步,用useLayoutEffect来同步执行,以希望比useEffect更早
    useLayoutEffect(() => {

        refs.forEach(item => {

            if (item == null) {
                return;
            }

            if (typeof item === 'function') {
                item(ref.current);
            } else {
                Object.assign(item, {current: ref.current});
            }
        });
    });

    return ref;
}
Example #22
Source File: useResizeObserver.ts    From celo-web-wallet with MIT License 6 votes vote down vote up
useResizeObserver = () => {
  const [observerEntry, setObserverEntry] = useState<ResizeObserverEntry | null>(null)
  const [nodeRef, setNodeRef] = useState<Element | null>(null)
  const observer = useRef<ResizeObserver | null>(null)

  const disconnect = useCallback(() => observer.current?.disconnect(), [])

  const observe = useCallback(() => {
    observer.current = new ResizeObserver((entries: ResizeObserverEntry[]) => {
      setObserverEntry(entries[0])
    })
    if (nodeRef) observer.current.observe(nodeRef)
  }, [nodeRef])

  useLayoutEffect(() => {
    observe()
    return () => disconnect()
  }, [disconnect, observe])

  return { setNodeRef, observerEntry }
}
Example #23
Source File: ChessBoard.tsx    From platform with MIT License 6 votes vote down vote up
function PGNViewer(props) {
  const { layout, size, mode="view" }  = props;
  const gameDescription = Children.onlyText(props.children);
  const id = "board-" + uuid.v4();

  useLayoutEffect(() => {
    pgnView(id, {
      pgn: gameDescription,
      mode,
      theme: "informator",
      layout: layout,
      hideMovesBefore: true,
      locale: "en",
      showResult: true,
      boardSize: size,
      showFen: false,
      pieceStyle: "alpha",
    });
  });

  return <div id={id}></div>;
}
Example #24
Source File: useComponentRegistry.ts    From r3f-game-demo with MIT License 6 votes vote down vote up
export default function useComponentRegistry<T extends ComponentRef>(
    name: T['name'],
    api: T['api']
) {
    const { registerComponent, unregisterComponent } = useGameObject();

    useLayoutEffect(() => {
        registerComponent<T>(name, api);
    });

    useLayoutEffect(() => {
        return () => unregisterComponent<T>(name);
    }, [unregisterComponent, name]);

    return api;
}
Example #25
Source File: GameLandingPageComponents.tsx    From client with GNU General Public License v3.0 6 votes vote down vote up
export function TerminalToggler({
  terminalEnabled,
  setTerminalEnabled,
}: {
  terminalEnabled: boolean;
  setTerminalEnabled: Dispatch<SetStateAction<boolean>>;
}) {
  const uiEmitter = UIEmitter.getInstance();
  useLayoutEffect(() => {
    uiEmitter.emit(UIEmitterEvent.UIChange);
  }, [terminalEnabled, uiEmitter]);

  return (
    <StyledTerminalToggler
      terminalEnabled={terminalEnabled}
      onClick={() => setTerminalEnabled((b: boolean): boolean => !b)}
    >
      <span>{terminalEnabled ? '>' : '<'}</span>
    </StyledTerminalToggler>
  );
}
Example #26
Source File: XAxis.tsx    From arduino-web-oscilloscope with MIT License 6 votes vote down vote up
export default function XAxis() {
  const nodeRef = useRef<SVGSVGElement>(null)
  const height = useRecoilValue(plotHeightSelector)
  const xScale = useRecoilValue(xScaleSelector)
  const gEl = nodeRef.current
  useLayoutEffect(() => {
    if (!gEl) return
    const xTicks = d3.ticks(xScale.domain()[0], xScale.domain()[1], 10)
    d3.select(gEl).call((g) =>
      g
        .attr('transform', `translate(0,${height - margin.bottom})`)
        .call(
          d3
            .axisBottom(xScale)
            .tickValues(xTicks)
            .tickPadding(10)
            .tickSize(-height + margin.top + margin.bottom)
            .tickFormat(formatTime)
            .tickSizeOuter(0)
        )
        .call((g) => g.select('.domain').remove())
    )
  }, [gEl, xScale, height])

  return <g className="x axis" ref={nodeRef} />
}
Example #27
Source File: UpdateSW.tsx    From nuzlocke with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
function UpdateSW(): JSX.Element {
  const [waitingServiceWorker, setWaitingServiceWorker] = useState(null);

  const setServiceWorker = useCallback(
    (registration: ServiceWorkerRegistration) => {
      setWaitingServiceWorker(registration.waiting);
    },
    [setWaitingServiceWorker]
  );

  useLayoutEffect(() => {
    window.setServiceWorker = setServiceWorker;
  }, [setServiceWorker]);

  const updateServiceWorker = () => {
    if (waitingServiceWorker) {
      waitingServiceWorker.postMessage({ type: 'SKIP_WAITING' });

      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      waitingServiceWorker.addEventListener('statechange', (e: any) => {
        if (e.target.state === 'activated') {
          window.location.reload();
        }
      });
    }
  };

  return waitingServiceWorker ? (
    <div className={styles.alert}>
      <span>New version available</span>
      <Button color="grey" onClick={updateServiceWorker} type="button">
        Update
      </Button>
    </div>
  ) : null;
}
Example #28
Source File: useColor.ts    From dyp with Do What The F*ck You Want To Public License 6 votes vote down vote up
export function useColor(token?: Token) {
  const [color, setColor] = useState('#2172E5')

  useLayoutEffect(() => {
    let stale = false

    if (token) {
      getColorFromToken(token).then(tokenColor => {
        if (!stale && tokenColor !== null) {
          setColor(tokenColor)
        }
      })
    }

    return () => {
      stale = true
      setColor('#2172E5')
    }
  }, [token])

  return color
}
Example #29
Source File: usePortal.ts    From ebs-design with MIT License 6 votes vote down vote up
usePortal = (id = 'portal') => {
  const wrapperRef = useRef<HTMLElement | null>(document.getElementById(id));

  if (wrapperRef.current === null && typeof document !== 'undefined') {
    const div = document.createElement('div');
    div.id = id;

    wrapperRef.current = div;
  }

  useLayoutEffect(() => {
    const wrapper = wrapperRef.current;

    if (!wrapper || typeof document === 'undefined') {
      return;
    }

    document.body.appendChild(wrapper);
  }, []);

  return (children) => wrapperRef.current && createPortal(children, wrapperRef.current);
}