Общие определения TypeScript, используемые в React

React.js

предисловие

учитесь во мнеtypescriptКогда, как вreactиспользуется вtypescriptПри написании кода неудобно начинать с нуля, потому что официальная документация не используетсяtypescriptБольшинство учебных пособий вы ищете в Интернете самостоятельно, и вы можете найти определение самостоятельно.

Итак, сегодня я подытожу и обобщу то, что использовал, надеясь помочь студентам, которые также изучают

следующий кодreactВерсия16.13.1,существуетcreate-react-appофициальныйtypescriptВ шаблоне нет ошибок

Введите бриф

НемногоReactвстроенный тип

  • React.ReactElement-- использоватьReact.createElementСоздан, можно просто понять какReactсерединаJSXЭлементы
  • React.ReactNode——<div>xxx</div>Легальные типы xxx
  • React.CSSProperties- встроенный компонентstyleтип объекта
  • React.RefObject——React.createRefСозданный тип, доступный только для чтения и неизменяемый
  • React.MutableRefObject——useRefСозданный тип, можно изменить
  • ...

объявление компонента

Объявления компонентов делятся на компоненты класса и компоненты функций.

компонент класса

Определения, используемые компонентами класса, в основномReact.Component<P,S>а такжеReact.PureComponent<P,S,SS>

interface AppProps {
  value: string;
}
interface AppState {
  count: number;
}
class App extends React.Component<AppProps, AppState> {
  static defaultProps = {
    value: "",
  };
  state = {
    count: 0,
  };
}

React.Component<P,S>здесьPдаpropsтип,Sдаstateтип, который можно записать какReact.Component<AppProp>,потому чтоstateТип будет выведен сам

наверхуPureComponentесть еще одноSS,этоSSдаgetSnapshotBeforeUpdateВозвращаемое значение

функциональный компонент

Есть два способа определить функциональные компоненты.React.FC, нужно напрямую датьpropsнапишите определение

interface AppProps {
  value?: string;
}

const App: React.FC<AppProps> = ({ value = '', children }) => {
    // ...
};

React.FCозначаетFunctionComponent, если использоватьReact.FC, который уже указан в определенииchildrenТип и возвращаемое значение функции, поэтому вы можете напрямую использоватьchildren

Если это прямоpropsНапишите определение, вам нужно определить его самостоятельноchildrenтип

interface AppProps {
  value?: string;
  children?: React.ReactNode; // 自己定义children的类型
}

function App({ value = "", children }: AppProps) {
  return <>{children}</>;
}

использоватьfunctionПреимущество определения вместо стрелочных функций заключается в том, что вы можете использовать общие компоненты

Заявление о крючках

hooksзаявление, если вы не знаете, как использоватьtsОпределение можно напрямую щелкнуть, чтобы увидеть

useState

useStateВы можете использовать общую передачу параметров или автоматический вывод

const [state, setState] = useState(''); // state的类型为string,自动推断
const [state, setState] = useState<string>(); // state的类型为 string | undefined
// 给初值
const [state, setState] = useState<string | null>(null); // state的类型为 string | null

useRef

useRefТакже делает вывод автоматически

const ref = useRef(""); // ref.current的类型为 string
// 泛型
type Value = { value: string };
const ref = useRef<Value>({ value: "" });
// ref为html元素
const ref = useRef<HTMLDivElement>(null);
return <div ref={ref} />;

Следует отметить, что еслиrefявляется элементом, то начальное значение записывается какnullне будет сообщать об ошибках

useReducer

useReducerУсловно говоря, есть еще что написать, и это может быть автоматически выведено, поэтому нет необходимости вручную писать общие типы (на самом деле, я не знаю, как писать Orz вручную)

// state类型
interface ReducerState {
  value: string;
}
// action类型
interface AnyAction {
  type: string;
  [key: string]: any;
}
// reducer函数
const reducer: React.Reducer<ReducerState, AnyAction> = (state, action) => {
  switch (action.type) {
    default:
      return state;
  }
};
// 初始值
const initialState: ReducerState = { value: "" };

const [state, dispatch] = useReducer(reducer, initialState);
// state 的类型为 ReducerState
// dispatch 的类型为 React.Dispatch<AnyAction>

Actionможет быть несколько разныхActionтип союза

useImperativeHandle

useImperativeHandleЭтот хук может передавать внутренние методы черезrefвыставлено, сtsТакже необходимо написать немного больше, и типы должны быть четко обозначены

Поэтому вам нужно использоватьReact.forwardRef, вы можете сначала увидеть следующий раздел

// props
interface AppProps {
  value: string;
}
// useImperativeHandle获取到ref的类型
interface Handle {
  get: () => string;
}

const App = React.forwardRef<Handle, AppProps>(({ value }, ref) => {
  // 定义
  useImperativeHandle(ref, () => ({
    get: () => `handle get value : ${value}`,
  }));
  return null;
});
// 使用
const handleRef = useRef<Handle>(null);
// handleRef.current?.get();
return <App value="hello" ref={handleRef} />;

Пользовательские крючки должны обратить внимание на

Есть следующие крючки

const useCustomHook = () => {
  const [state, setState] = useState("");
  const set = (value: string) => {
    if (!value) return;
    setState(value);
  };
  return [state, set];
};
// 使用
const [state, setState] = useCustomHook();
setState('hello') // This expression is not callabl

Пользовательские хуки также должны определять возвращаемые значения.

- const useCustomHook = () => {
+ const useCustomHook = (): [string, (value: string) => void] => {

React.forwardRef

React.forwardRef<T, P = {}>просто пройтиpropsтип иrefтипа, первыйTдаrefтип,Pдаpropsтип

const App = React.forwardRef<HTMLDivElement, AppProps>(({ value }, ref) => {
  return <div ref={ref} />;
});
// 使用
const ref = useRef<HTMLDivElement>(null);
return <App value="hello" ref={ref} />;

React.ForwardRefRenderFunction

Функции, определенные как этот тип, могут быть помещены вReact.forwardRefфункция как параметр

// 定义
const forwardRender: React.ForwardRefRenderFunction<
  HTMLDivElement,
  AppProps
> = ({ value }, ref) => {
  return <div ref={ref} />;
};
const App = React.forwardRef(forwardRender);
// 使用
const ref = useRef<HTMLDivElement>(null);
return <App value="hello" ref={ref} />;

React.createContext

Обобщения имеют функцию автоматического вывода, поэтомуuseContextБольше не нужно писать тип

interface ContextType {
  getPrefixCls: (value: string) => string;
}

const context = React.createContext<ContextType>({
  getPrefixCls: (value) => `prefix-${value}`,
});

const App = () => {
  const { getPrefixCls } = useContext(context);
  getPrefixCls("App"); // prefix-App
  return null;
};

React.cloneElement

если используетсяReact.FCопределенный компонент, егоchildrenВведите значение по умолчаниюReact.ReactNode, который необходимо явно преобразовать вReact.ReactElement

const App: React.FC = ({ children }) => {
  return React.cloneElement(children as React.ReactElement, { value: "hello" });
};
// 也可以覆写定义
const App: React.FC<{ children: React.ReactElement }> = ({ children }) => {
  return React.cloneElement(children, { value: "hello" });
};

React.ComponentType

пройти черезReact.ComponentType<P>Определенный компонент может передать имя переменной компоненту и вызвать его внутри компонента.Компоненты более высокого порядка обычно используют

interface AppProps {
  value: string;
}
const App: React.FC<AppProps> = (props) => {
  return null;
};
// React.ComponentType定义组件
function HOC<T>(Component: React.ComponentType<T>) {
  return function (props: T) {
    return <Component {...props} />;
  };
}
const WrappedComponent = HOC(App);
// 调用
<WrappedComponent value="hello" />

Компоненты общих параметров

Компоненты общего параметра:typescriptНовое в версии 2.9, первый раз увидел вant-deisgnвнутри

Очень простой примерSelectкомпоненты

<Select<number>>
  <Select.Option value={1}>1</Select.Option>
  <Select.Option value={2}>2</Select.Option>
</Select>

определение компонента класса

// 定义泛型参数的组件
class GenericComponent<P> extends React.Component<P> {
  internalProp: P;
  constructor(props: P) {
    super(props);
    this.internalProp = props;
  }
  render() {
    return null;
  }
}

type Props = { a: number; b: string };

<GenericComponent<Props> a={10} b="hi" />; // OK
<GenericComponent<Props> a={10} b={20} />; // Error

Определение функциональных компонентов

function GenericComponent<P>(props: P) {
  const internalProp = useRef(props)
  return null;
}

Компоненты стрелочных функций также могут использовать дженерики при определенных условиях.

// 这样会解析错误
const GenericComponent = <P>(props: P) =>{
  const internalProp = useRef(props);
  return null;
}

// 泛型必须使用extends关键字才能解析
const GenericComponent = <P extends any>(props: P) =>{
  const internalProp = useRef(props);
  return null;
}

Функциональные компоненты могут быть написаны гораздо более лаконично...

обработка событий

также разнообразный

const App = () => {
  // React.MouseEventHandler
  const onClick: React.MouseEventHandler<HTMLInputElement> = (e) => {
    console.log(e.currentTarget.value);
  };
  // React.ChangeEventHandler
  const onChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
    console.log(e.currentTarget.value);
  };
  // React.FocusEventHandler
  const onFocus: React.FocusEventHandler<HTMLInputElement> = (e) => {
    console.log(e.currentTarget.value);
  };
  return <input onClick={onClick} onChange={onChange} onFocus={onFocus} />;
};

Если есть событие, для которого непонятно, как определить тип, вы можете щелкнуть имя события на компоненте, чтобы увидеть определение.

Следует отметить, что толькоe.currentTargetБудет соответствующий тип элемента,e.targetнет, его типEventTarget

Суммировать

Ничего другого не могу придумать, добавлю еще, когда вспомню

tsПоставляется с некоторыми универсальными инструментами, такими какOmit,Pick,Это все еще полезно при разработке, вы можете увидеть мои предыдущиеСуммировать

Напоследок желаю всем крепкого здоровья и легкой работы!


Жаль, что в tsx нет даже подсветки кода, можно только сказать, что она до сих порprismjsочень хорошо,highlightjsне очень хорошо