useState
useState 如果初始值不是null/undefined 的话,是具备类型推导能力的,根据传入的初始值推断出类型;初始值是 null/undefined 的话则需要传递类型定义才能进行约束。一般情况下,还是推荐传入类型(通过useState的第一个泛型参数)。
const [value, setValue] = useState(0);
interface MyObject {
foo: string;
bar?: number;
}
const [value, setValue] = useState<MyObject>(null);
useContext
useContext 一般根据传入的Context的值就可以推断出返回值。不需要显示传递类型
type Theme = 'light' | 'dark';
const ThemeContext = createContext<Theme>('dark');
const App = () => (
<ThemeContext.Provider value="dark">
<MyComponent />
</ThemeContext.Provider>
)
const MyComponent = () => {
const theme = useContext(ThemeContext);
return <div>The theme is {theme}</div>;
useEffect useLayoutEffect 没有返回值,无需传递类型 useCallback useMemo
useMemo 无需传递类型,根据函数的返回值就能推断出类型
useCallback 无需传递类型,根据函数的返回值就能推断出类型。但是注意函数的入参需要定义类型,不然就是推断为any了!
const value = 10;
const result = useMemo(() => value * 2, [value]);
const multiplier = 2;
const multiply = useCallback((value: number) => value * multiplier, [multiplier]);
useRef
useRef 传非空初始值的时候可以推断类型,同样也可以通过传入第一个泛型参数来定义类型,约束ref.current 的类型。
const MyInput = () => {
const inputRef = useRef<HTMLInputElement>(null);
return <input ref={inputRef} />
}
const myNumberRef = useRef(0);
myNumberRef.current += 1;
useReducer
只需要对传入useReducer 的reducer函数的入参state 和action 进行类型约束就能够推断出来
interface State {
value: number;
}
type Action =
| { type: 'increment' }
| { type: 'decrement' }
| { type: 'incrementAmount'; amount: number };
const counterReducer = (state: State, action: Action) => {
switch (action.type) {
case 'increment':
return { value: state.value + 1 };
case 'decrement':
return { value: state.value - 1 };
case 'incrementAmount':
return { value: state.value + action.amount };
default:
throw new Error();
}
};
const [state, dispatch] = useReducer(counterReducer, { value: 0 });
dispatch({ type: 'increment' });
dispatch({ type: 'decrement' });
dispatch({ type: 'incrementAmount', amount: 10 });
dispatch({ type: 'invalidActionType' });
useImperativeHandle
useImperativeHandle 一般比较少用,一般用来选择函数组件对外暴露ref属性被调用,需要配合forwardRef 使用。
如下例子。需要定义对外暴露的接口MyInputHandles ,函数组件使用React.RefForwardingComponent 对外暴露的接口调用作为泛型参数。然后就会得到约束了
export interface MyInputHandles {
focus(): void;
}
const MyInput: RefForwardingComponent<MyInputHandles, MyInputProps> = (
props,
ref
) => {
const inputRef = useRef<HTMLInputElement>(null);
useImperativeHandle(ref, () => ({
focus: () => {
if (inputRef.current) {
inputRef.current.focus();
}
},
}));
return <input {...props} ref={inputRef} />;
};
export default forwardRef(MyInput);
const Autofocus = () => {
const myInputRef = useRef<MyInputHandles>(null);
useEffect(() => {
if (myInputRef.current) {
myInputRef.current.focus();
}
});
return <MyInput ref={myInputRef} />
}
参考:
React Hooks in TypeScript
|