Skip to content

Commit

Permalink
perf: useSafeState
Browse files Browse the repository at this point in the history
  • Loading branch information
hemengke1997 committed Dec 6, 2021
1 parent 2c80499 commit cde740d
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 6 deletions.
8 changes: 4 additions & 4 deletions src/ResizableHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { ThHTMLAttributes } from 'react';
import { Resizable, ResizeCallbackData } from 'react-resizable';
import classnames from 'classnames';
import useSafeState from './utils/useSafeState';

import './index.css';

Expand Down Expand Up @@ -33,7 +34,7 @@ const ResizableHeader: React.FC<ComponentProp> = (props) => {

const thRef = React.useRef<HTMLTableCellElement>(null);

const [resizeWidth, setResizeWidth] = React.useState<number>(0);
const [resizeWidth, setResizeWidth] = useSafeState<number>(0);

React.useEffect(() => {
if (width) {
Expand All @@ -54,7 +55,6 @@ const ResizableHeader: React.FC<ComponentProp> = (props) => {
{...rest}
style={style}
className={className}
title={title}
onClick={onClick}
rowSpan={rowSpan}
colSpan={colSpan}
Expand Down Expand Up @@ -111,15 +111,15 @@ const ResizableHeader: React.FC<ComponentProp> = (props) => {
e.stopPropagation();
}}
>
<div className="resizable-line"></div>
<div className="resizable-line" />
</div>
}
draggableOpts={{ enableUserSelectHack: false }}
onResizeStart={onStart}
onResize={onSelfResize}
onResizeStop={onStop}
>
<div style={{ width: resizeWidth, height: '100%' }}></div>
<div style={{ width: resizeWidth, height: '100%' }} />
</Resizable>
<div {...rest} className="resizable-title">
<span title={title}>{children}</span>
Expand Down
5 changes: 3 additions & 2 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import useThrottleEffect from './utils/useThrottleEffect';
import useDebounceFn from './utils/useDebounceFn';
import { depthFirstSearch, getUniqueId, ResizableUniqIdPrefix } from './utils';
import useDeepFnCompareEffect from './utils/useDeepFnCompareEffect';
import useSafeState from './utils/useSafeState';

type useTableResizableHeaderProps<ColumnType> = {
columns: ColumnType[] | undefined;
Expand Down Expand Up @@ -37,9 +38,9 @@ function useTableResizableHeader<ColumnType extends Record<string, any>>(
// add column width cache to avoid column's width reset after render
const widthCache = React.useRef<Map<React.Key, CacheType>>(new Map());

const [resizableColumns, setResizableColumns] = React.useState<ColumnType[]>(columns || []);
const [resizableColumns, setResizableColumns] = useSafeState<ColumnType[]>(columns || []);

const [tableWidth, setTableWidth] = React.useState<number>();
const [tableWidth, setTableWidth] = useSafeState<number>();

const [triggerRender, forceRender] = React.useReducer((s) => s + 1, 0);

Expand Down
21 changes: 21 additions & 0 deletions src/utils/useSafeState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useCallback, useState } from 'react';
import type { Dispatch, SetStateAction } from 'react';
import useUnmountedRef from './useUnmountedRef';

function useSafeState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];

function useSafeState<S = undefined>(): [S | undefined, Dispatch<SetStateAction<S | undefined>>];

function useSafeState<S>(initialState?: S | (() => S)) {
const unmountedRef = useUnmountedRef();
const [state, setState] = useState(initialState);
const setCurrentState = useCallback((currentState) => {
/** if component is unmounted, stop update */
if (unmountedRef.current) return;
setState(currentState);
}, []);

return [state, setCurrentState] as const;
}

export default useSafeState;
14 changes: 14 additions & 0 deletions src/utils/useUnmountedRef.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useEffect, useRef } from 'react';

const useUnmountedRef = () => {
const unmountedRef = useRef(false);
useEffect(() => {
unmountedRef.current = false;
return () => {
unmountedRef.current = true;
};
}, []);
return unmountedRef;
};

export default useUnmountedRef;

0 comments on commit cde740d

Please sign in to comment.