React TypeScript:使用useRef进行OnChange的HTML Select的正确引用类型

时间:2019-09-18 02:53:04

标签: reactjs typescript

我以前没有在选择框上使用过useRef钩子,打字稿似乎在抱怨我引用的类型错误?

import React, {useState, useRef} from 'react';


const App: React.FC = () => {
  const [state, setState] = useState({country: ''});
  const formValue = (event: React.ChangeEvent<HTMLInputElement>) => {setState({...state, [event.target.name]: event.target.value.trim()})}
  const country = useRef<HTMLSelectElement>(null);

  return (
    <div className="layout-grid">
      <div className='layout-title'>Identity</div>

      <div className='section-grid'>
        <div>Country Information</div>
        <div>
          <label>Country</label>
          <select ref='country' onChange={formValue} name="country" value={state.country} >
            <option value="First Choice">First Choice</option>
            <option value="Second Choice">Second Choice</option>
            <option value="Third Choice">Third Choice</option>
            <option value="Fourth Choice">Fourth Choice</option>
          </select>
        </div>
      </div>

我得到的错误是

Type '(event: ChangeEvent<HTMLInputElement>) => void' is not assignable to type '(event: ChangeEvent<HTMLSelectElement>) => void'.
  Types of parameters 'event' and 'event' are incompatible.
    Type 'ChangeEvent<HTMLSelectElement>' is not assignable to type 'ChangeEvent<HTMLInputElement>'.
      Type 'HTMLSelectElement' is missing the following properties from type 'HTMLInputElement': accept, align, alt, checked, and 33 more.ts(2322)
index.d.ts(2117, 9): The expected type comes from property 'onChange' which is declared here on type 'DetailedHTMLProps<SelectHTMLAttributes<HTMLSelectElement>, HTMLSelectEle

1 个答案:

答案 0 :(得分:2)

由于HTMLInputElement位于HTMLSelectElement(而非onChange)上,因此可以通过将selectinput交换来解决问题类型错误。

要使用ref,必须传递使用useRefcountry)创建的ref变量(而不是字符串"country")。

const App: React.FC = () => {
  const [state, setState] = React.useState({ country: "" });
  const formValue = (event: React.ChangeEvent<HTMLSelectElement>) => {
    setState({ ...state, [event.target.name]: event.target.value.trim() });
  };
  const country = React.useRef<HTMLSelectElement>(null);

  // On first render, this will be null. Subsequent renders with log the value.
  console.log(country.current && country.current.value)

  return (
    <div className="layout-grid">
      <div className="layout-title">Identity</div>

      <div className="section-grid">
        <div>Country Information</div>
        <div>
          <label>Country</label>
          <select
            ref={country}
            onChange={formValue}
            name="country"
            value={state.country}
          >
            <option value="First Choice">First Choice</option>
            <option value="Second Choice">Second Choice</option>
            <option value="Third Choice">Third Choice</option>
            <option value="Fourth Choice">Fourth Choice</option>
          </select>
        </div>
      </div>
    </div>
  );
};

编辑:回答您的评论:

如果您想重用formValue,可以将可能的元素的联合类型传递给ChangeEvent。例如:

  const formValue = (
    event: React.ChangeEvent<HTMLSelectElement | HTMLInputElement>
  ) => {
    setState({ ...state, [event.target.name]: event.target.value.trim() });
  };