Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions docs/examples/dynaymicCSS.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ function injectStyle(id: number, prepend?: Prepend, priority?: number) {
});
}

export default () => {
const Demo = () => {
const [id, setId] = React.useState(0);
const idRef = React.useRef(id);
const idRef = React.useRef<number>(id);
idRef.current = id;

// Clean up
Expand Down Expand Up @@ -55,3 +55,5 @@ export default () => {
</>
);
};

export default Demo;
18 changes: 8 additions & 10 deletions docs/examples/getScrollBarSize.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ const cssText = `
}
`;

export default () => {
const defaultRef = React.useRef<HTMLDivElement>();
const webkitRef = React.useRef<HTMLDivElement>();
const scrollRef = React.useRef<HTMLDivElement>();
const Demo = () => {
const defaultRef = React.useRef<HTMLDivElement>(null);
const webkitRef = React.useRef<HTMLDivElement>(null);
const scrollRef = React.useRef<HTMLDivElement>(null);

const [sizeData, setSizeData] = React.useState('');

React.useEffect(() => {
Expand All @@ -45,12 +46,7 @@ export default () => {

return (
<div>
<style
dangerouslySetInnerHTML={{
__html: cssText,
}}
/>

<style dangerouslySetInnerHTML={{ __html: cssText }} />
<div
style={{
width: 300,
Expand Down Expand Up @@ -87,3 +83,5 @@ export default () => {
</div>
);
};

export default Demo;
12 changes: 7 additions & 5 deletions docs/examples/portal.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React from 'react';
import PortalWrapper from 'rc-util/es/PortalWrapper';

export default () => {
const divRef = React.useRef();
const outerRef = React.useRef();
const Demo: React.FC = () => {
const divRef = React.useRef<HTMLDivElement>(null);
const outerRef = React.useRef<HTMLDivElement>(null);

React.useEffect(() => {
console.log('>>>', divRef.current);
}, []);

function getRef() {
return outerRef.current;
}
Expand All @@ -18,7 +18,9 @@ export default () => {
<PortalWrapper visible getContainer={getRef}>
{() => <div ref={divRef}>2333</div>}
</PortalWrapper>
<div style={{ background: 'red', height: 20 }} ref={outerRef} />
<div style={{ backgroundColor: 'red', height: 20 }} ref={outerRef} />
</>
);
};

export default Demo;
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"@testing-library/react": "^16.0.0",
"@types/jest": "^30.0.0",
"@types/node": "^24.6.1",
"@types/react": "^18.0.0",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.2",
"@types/react-is": "^19.0.0",
"@types/responselike": "^1.0.0",
Expand Down
7 changes: 4 additions & 3 deletions src/Portal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ export interface PortalProps {
const Portal = forwardRef<PortalRef, PortalProps>((props, ref) => {
const { didUpdate, getContainer, children } = props;

const parentRef = useRef<ParentNode>();
const containerRef = useRef<HTMLElement>();
const parentRef = useRef<ParentNode>(null);
const containerRef = useRef<HTMLElement>(null);

// Ref return nothing, only for wrapper check exist
useImperativeHandle(ref, () => ({}));

// Create container in client side with sync to avoid useEffect not get ref
const initRef = useRef(false);
const initRef = useRef<boolean>(false);

if (!initRef.current && canUseDom()) {
containerRef.current = getContainer();
parentRef.current = containerRef.current.parentNode;
Expand Down
7 changes: 3 additions & 4 deletions src/hooks/useEffect.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import * as React from 'react';

/** As `React.useEffect` but pass origin value in callback and not need care deps length change. */
export default function useEffect(
callback: (prevDeps: any[]) => void,
deps: any[],
) {
function useEffect(callback: (prevDeps: any[]) => void, deps: any[]) {
const prevRef = React.useRef(deps);
React.useEffect(() => {
if (
Expand All @@ -16,3 +13,5 @@ export default function useEffect(
prevRef.current = deps;
});
}

export default useEffect;
2 changes: 1 addition & 1 deletion src/hooks/useLayoutEffect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const useLayoutEffect = (
callback: (mount: boolean) => void | VoidFunction,
deps?: React.DependencyList,
) => {
const firstMountRef = React.useRef(true);
const firstMountRef = React.useRef<boolean>(true);

useInternalLayoutEffect(() => {
return callback(firstMountRef.current);
Expand Down
12 changes: 5 additions & 7 deletions src/hooks/useState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,12 @@ export type SetState<T> = (
* We do not make this auto is to avoid real memory leak.
* Developer should confirm it's safe to ignore themselves.
*/
export default function useSafeState<T>(
defaultValue?: T | (() => T),
): [T, SetState<T>] {
const destroyRef = React.useRef(false);
const useSafeState = <T>(defaultValue?: T | (() => T)): [T, SetState<T>] => {
const destroyRef = React.useRef<boolean>(false);
const [value, setValue] = React.useState(defaultValue);

React.useEffect(() => {
destroyRef.current = false;

return () => {
destroyRef.current = true;
};
Expand All @@ -34,9 +31,10 @@ export default function useSafeState<T>(
if (ignoreDestroy && destroyRef.current) {
return;
}

setValue(updater);
}

return [value, safeSetState];
}
};

export default useSafeState;
8 changes: 4 additions & 4 deletions src/hooks/useSyncState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ export type SetState<T> = (nextValue: Updater<T>) => void;
* This is useful when React merge multiple state updates into one.
* e.g. onTransitionEnd trigger multiple event at once will be merged state update in React.
*/
export default function useSyncState<T>(
defaultValue?: T,
): [get: () => T, set: SetState<T>] {
function useSyncState<T>(defaultValue?: T): [get: () => T, set: SetState<T>] {
const [, forceUpdate] = React.useReducer(x => x + 1, 0);

const currentValueRef = React.useRef(defaultValue);
const currentValueRef = React.useRef<T>(defaultValue);

const getValue = useEvent(() => {
return currentValueRef.current;
Expand All @@ -32,3 +30,5 @@ export default function useSyncState<T>(

return [getValue, setValue];
}

export default useSyncState;
8 changes: 5 additions & 3 deletions tests/ref-19.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ describe('ref: React 19', () => {
});

it('useComposeRef', () => {
const Demo = ({ children }: { children: React.ReactElement }) => {
const Demo: React.FC<React.PropsWithChildren> = ({ children }) => {
const ref = React.useRef<HTMLDivElement>(null);
const childRef = getNodeRef(children); // Should get child real `ref` props
const mergedRef = useComposeRef(ref, childRef);
Expand All @@ -59,7 +59,10 @@ describe('ref: React 19', () => {

return (
<>
{React.cloneElement(children, { ref: mergedRef })}
{React.cloneElement<{ ref?: any }>(
children as React.ReactElement<any>,
{ ref: mergedRef },
)}
<div className="test-output">{childClassName}</div>
</>
);
Expand All @@ -79,7 +82,6 @@ describe('ref: React 19', () => {

it('supportRef with not provide ref', () => {
const Empty = () => <div />;

const Checker = ({ children }: { children: React.ReactElement }) => {
return <p>{String(supportRef(children))}</p>;
};
Expand Down
7 changes: 4 additions & 3 deletions tests/ref.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,12 @@ describe('ref', () => {
it('useComposeRef not changed', () => {
let count = 0;

const Demo = () => {
const Demo: React.FC = () => {
const [, forceUpdate] = React.useState({});

const ref1 = React.useRef();
const ref2 = React.useRef();
const ref1 = React.useRef<HTMLButtonElement>(null);
const ref2 = React.useRef<HTMLButtonElement>(null);

const refFn = useEvent(() => {
count += 1;
});
Expand Down
6 changes: 1 addition & 5 deletions tests/toArray-19.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ jest.mock('react-dom/test-utils', () => {
return reactDom19Test;
});

class UL extends React.Component<{
children?: React.ReactNode;
}> {
class UL extends React.Component<React.PropsWithChildren<any>> {
render() {
return <ul>{this.props.children}</ul>;
}
Expand All @@ -33,7 +31,6 @@ class UL extends React.Component<{
describe('toArray', () => {
it('Fragment', () => {
const ulRef = React.createRef<UL>();

render(
<UL ref={ulRef}>
<li key="1">1</li>
Expand All @@ -49,7 +46,6 @@ describe('toArray', () => {
</React.Fragment>
</UL>,
);

const children = toArray(ulRef.current.props.children);
expect(children).toHaveLength(5);
expect(children.map(c => c.key)).toEqual(['1', '2', '3', '4', '5']);
Expand Down
Loading