Можно ли вывести сигнатуру типа useCallback для обработчика событий? - PullRequest
2 голосов
/ 14 февраля 2020

Я использую TypeScript с React и использую функцию стрелки в качестве обратного вызова для UI материала <Select> компонент :

import React from 'react';
import MenuItem from '@material-ui/core/MenuItem';
import Select from '@material-ui/core/Select';

interface Props {
  value: string;
  onSelect: (value: string) => void;
}

function MySelector(props: Props) {
  return (
    <Select
      value={props.value}
      onChange={e => props.onSelect(e.value as string)}
    >
      <MenuItem value="a">A</MenuItem>
      <MenuItem value="b">B</MenuItem>
      <MenuItem value="c">C</MenuItem>
    </Select>
  )
}

Чтобы избежать передачи новой функции каждый раз, когда MySelector рендерит, я бы хотел использовать useCallback hook . Хотя прямой рефакторинг работает во время выполнения, он не может выполнить проверку из-за неявной ошибки any в параметре события, e:

function MySelector(props: Props) {
  const handleChange = React.useCallback(
    e => props.onSelect(e.value as string),
 // ~ e implicitly has an any type
    [props.onSelect]
  );
  return (
    <Select
      value={props.value}
      onChange={handleChange}
    >
      { /* ... menu items ... */ }
    </Select>
  )
}

Наведение над символом e в исходных шоу это типа

React.ChangeEvent<{
    name?: string | undefined;
    value: unknown;
}>

Это глоток, но чтобы исправить ошибку, вот что я должен вставить:

const handleChange = React.useCallback(
  (
    e: React.ChangeEvent<{
      name?: string | undefined;
      value: unknown;
    }>,
  ) => props.onSelect(e.value as string),
  [props.onSelect],
);

Могу ли я взять свой пирог и съесть его тоже? Могу ли я использовать хук useCallback и все же получить тип параметра события из контекста?

1 Ответ

0 голосов
/ 14 февраля 2020

Если вы используете только value свойство из события, вы можете уйти с:

const handleChange = React.useCallback(
  (e: React.ChangeEvent<{value: string}>) => props.onSelect(e.value),
  [props.onSelect],
);
...