feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { act, renderHook } from '@testing-library/react-hooks';
|
||||
import useStateRealtime from '../index';
|
||||
|
||||
describe('useStateRealtime', () => {
|
||||
it('initState undefined', () => {
|
||||
const { result } = renderHook(() => useStateRealtime());
|
||||
const [state, setState, getRealVal] = result.current;
|
||||
expect(state).toBeUndefined();
|
||||
});
|
||||
it('initState number 2', () => {
|
||||
const { result } = renderHook(() => useStateRealtime(2));
|
||||
const [state, setState, getRealVal] = result.current;
|
||||
expect(state).toBe(2);
|
||||
});
|
||||
it('initState function 10', () => {
|
||||
const { result } = renderHook(() => useStateRealtime(() => 10));
|
||||
const [state, setState, getRealVal] = result.current;
|
||||
expect(state).toBe(10);
|
||||
});
|
||||
it('method setState', () => {
|
||||
const { result } = renderHook(() => useStateRealtime(1));
|
||||
const [state, setState, getRealVal] = result.current;
|
||||
expect(result.current[0]).toBe(1);
|
||||
act(() => {
|
||||
setState(2);
|
||||
});
|
||||
expect(result.current[0]).toBe(2);
|
||||
});
|
||||
it('method setState param function', () => {
|
||||
const { result } = renderHook(() => useStateRealtime(() => 10));
|
||||
const [state, setState, getRealVal] = result.current;
|
||||
expect(result.current[0]).toBe(10);
|
||||
act(() => {
|
||||
setState(pre => pre + 2);
|
||||
});
|
||||
expect(result.current[0]).toBe(12);
|
||||
});
|
||||
it('method getRealVal', () => {
|
||||
const { result } = renderHook(() => useStateRealtime(1));
|
||||
const [state, setState, getRealVal] = result.current;
|
||||
act(() => {
|
||||
setState(2);
|
||||
});
|
||||
expect(getRealVal()).toBe(2);
|
||||
});
|
||||
it('method getRealVal function', () => {
|
||||
const { result } = renderHook(() => useStateRealtime(() => 10));
|
||||
const [state, setState, getRealVal] = result.current;
|
||||
act(() => {
|
||||
setState(pre => pre + 2);
|
||||
});
|
||||
expect(getRealVal()).toBe(12);
|
||||
});
|
||||
it('test batchUpdate', () => {
|
||||
const { result } = renderHook(() => useStateRealtime(1));
|
||||
const [state, setState, getRealVal] = result.current;
|
||||
act(() => {
|
||||
setState(pre => pre + 2);
|
||||
expect(getRealVal()).toBe(3);
|
||||
setState(pre => pre + 2);
|
||||
expect(getRealVal()).toBe(5);
|
||||
});
|
||||
expect(result.current[0]).toBe(5);
|
||||
expect(getRealVal()).toBe(5);
|
||||
act(() => {
|
||||
setState(pre => pre + 4);
|
||||
expect(getRealVal()).toBe(9);
|
||||
setState(pre => pre + 4);
|
||||
expect(getRealVal()).toBe(13);
|
||||
});
|
||||
expect(result.current[0]).toBe(13);
|
||||
expect(getRealVal()).toBe(13);
|
||||
});
|
||||
});
|
||||
46
frontend/packages/arch/hooks/src/use-state-realtime/index.ts
Normal file
46
frontend/packages/arch/hooks/src/use-state-realtime/index.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useState, useRef, type Dispatch, type SetStateAction, useCallback } from 'react';
|
||||
|
||||
const isFunction = (val: any): val is Function => typeof val === 'function';
|
||||
|
||||
// 获取新的状态值,兼容传值和传函数情况
|
||||
function getStateVal<T>(preState: T, initVal?: SetStateAction<T>): T | undefined {
|
||||
if (isFunction(initVal)) {
|
||||
return initVal(preState);
|
||||
}
|
||||
return initVal;
|
||||
}
|
||||
|
||||
function useStateRealtime<T>(initialState: T | (() => T)): [T, Dispatch<SetStateAction<T>>, () => T]
|
||||
function useStateRealtime<T = undefined>(): [T | undefined, Dispatch<SetStateAction<T | undefined>>, () => T | undefined]
|
||||
function useStateRealtime<T>(
|
||||
initVal?: T | (() => T),
|
||||
): [T | undefined, Dispatch<SetStateAction<T | undefined>>, () => T | undefined] {
|
||||
const initState = getStateVal(undefined, initVal);
|
||||
const [val, setVal] = useState(initState);
|
||||
const valRef = useRef(initState);
|
||||
const setState = useCallback((newVal?: SetStateAction<T | undefined>) => {
|
||||
const newState = getStateVal(valRef.current, newVal);
|
||||
valRef.current = newState;
|
||||
setVal(newState);
|
||||
}, [])
|
||||
const getRealState = useCallback(() => valRef.current, [])
|
||||
return [val, setState, getRealState];
|
||||
}
|
||||
|
||||
export default useStateRealtime;
|
||||
Reference in New Issue
Block a user