【问题标题】:Autosuggest renderInputComponent - inputProps types of property 'onChange' are incompatible自动建议 renderInputComponent - 属性“onChange”的 inputProps 类型不兼容
【发布时间】:2020-08-30 06:56:15
【问题描述】:

在将react-autosuggest 与自定义输入样式组件一起使用时,我遇到了这个 Typescript 错误。

属性“onChange”的类型不兼容。类型 '(event: FormEvent, params: ChangeEvent) => void' 不可分配给类型 '(event: ChangeEvent) => void'。

代码: (注意不完整,只是相关部分)

// styled.ts
export const Input = styled.input`
  // styles
`;

// index.tsx
function renderInput(
  inputProps: Autosuggest.InputProps<SuggestionSearch>,
  placeholder: string
) {
  // --> error here
  return <Input {...inputProps} placeholder={placeholder} />;
}

const MyComponent = () => {
  const autosuggestRef = React.useRef<
    Autosuggest<SuggestionSearch, SuggestionSearch>
  >(null);

  const onChange = (event: React.FormEvent, { newValue }: ChangeEvent) =>
    setValue(newValue);

  const inputProps = {
    value,
    onChange,
    onKeyPress: onEnterPress,
  };

  return (
    <Autosuggest
      ref={autosuggestRef}
      renderInputComponent={props => renderInput(props, placeholder)}
      inputProps={inputProps}
      // other props
    />
  )
}

不确定如何解决此问题,因为 Autosuggest onChange 函数会覆盖基本输入 onChange 属性。

【问题讨论】:

    标签: javascript reactjs typescript styled-components


    【解决方案1】:

    我自己花了整晚的时间来解决这个问题。看来这是一个错误。这是InputProps的签名:

        interface InputProps<TSuggestion>
            extends Omit<React.InputHTMLAttributes<any>, 'onChange' | 'onBlur'> {
            onChange(event: React.FormEvent<any>, params: ChangeEvent): void;
            onBlur?(event: React.FocusEvent<any>, params?: BlurEvent<TSuggestion>): void;
            value: string;
        }
    

    看来我们需要创建自己的Input 组件来接收这种类型的onChange 签名,或者将这个onChange 包装在标准的onChange 中。

    所以,这是我的方法:

    const renderInputComponent = (inputProps: InputProps<TSuggestion>): React.ReactNode => {
        const onChangeHandler = (event: React.ChangeEvent<HTMLInputElement>): void => {
          inputProps.onChange(event, { newValue: event.target.value, method: 'type' });
        };
       return <Input {...inputProps} onChange={onChangeHandler} />;
    }
    

    两个潜在的错误:

    • 请注意,返回的eventReact.ChangeEvent,而不是React.FormEvent。微小的差异,但如果您实际使用它并且对事件足够特别,它可能会在运行时出现问题。
    • 返回的params: ChangeEvent只占type事件方法。如果你想要其他的,比如click、esc等等……你必须自己补充(例如通过onKeyUp,然后调用`onChange(...{method: 'esc'})

    根据文档:

    注意:在使用 renderInputComponent 时,仍然需要指定通常的 inputProps。 Autosuggest 会将您提供的 inputProps 与可访问性所需的其他 props 合并(例如“aria-activedescendant”),并将合并后的 inputProps 传递给 renderInputComponent。

    你不必这样做:

    renderInputComponent={props => renderInput(props, placeholder)}
    

    只需将placeholder 直接传递给您的inputProps,它就会在renderInputComponent 中直接返回给您。

      const inputProps = {
        value,
        onChange,
        onKeyPress: onEnterPress,
        placeholder: 'something!`
      };
    

    【讨论】:

      【解决方案2】:

      我的问题是 renderInputComponent 上的 onChange() 不会触发 onSuggestionsFetchRequested

      如果我不使用自定义输入(通过 renderInputComponent),那么一切正常 - 触发 onSuggestionsFetchRequested 并显示建议列表。

      主要组件

          const MySearchBox: FC<MySearchBoxProps> = (props) => {
          
          // Autosuggest will pass through all these props to the input.
          const inputProps = {
              placeholder: props.placeholder,
              value: props.value,
              onChange: props.onChange
          };
      
          return (
              <Autosuggest
                  suggestions={props.suggestions}
                  onSuggestionsFetchRequested={props.onSuggestionsFetechRequested}
                  onSuggestionsClearRequested={props.onSuggestionsClearRequested}
                  getSuggestionValue={props.getSuggestionValue}
                  shouldRenderSuggestions={(value) => value.trim().length > 2}
                  renderSuggestion={(item: ISuggestion) => {
                      <div className={classes.suggestionsList}>{`${item.text} (${item.id})`}</div>;
                  }}
                  renderInputComponent={(ip: InputProps<ISuggestion>) => {
                      const params: InputProps<ISuggestion> = {
                          ...ip,
                          onChange: props.onChange
                      };
                      return renderInput(params);
                  }}
                  inputProps={inputProps}
                  
              />
          );
      };
      
      export { MySearchBox };
      

      自定义输入组件

      import React, { FC, ChangeEvent } from 'react';
      import SearchIcon from '@material-ui/icons/Search';
      import useStyles from './searchInput.styles';
      import { Input } from '@material-ui/core';
      
      type SearchInputBoxProps = {
          loading?: boolean;
          searchIconName: string;
          minWidth?: number;
          placeHolder?: string;
          onChange?: (e: ChangeEvent, params: { newValue: string; method: string }) => void;
      };
      
      const SearchInputBox: FC<SearchInputBoxProps> = (props) => {
          const classes = useStyles();
      
          return (
              <div className={classes.root}>
                  <div className={classes.searchIcon}>
                      <SearchIcon />
                  </div>
      
                  <Input
                      placeholder={props.placeHolder}
                      classes={{
                          root: classes.inputContainer,
                          input: classes.inputBox
                      }}
                      inputProps={{ 'aria-label': 'search' }}
                      onChange={(e) => {
                          const params: { newValue: string; method: string } = {
                              newValue: e.target.value,
                              method: 'type'
                          };
                          console.log(`e: ${JSON.stringify(params)}`);
                          if (props.onChange) props.onChange(e, params);
                      }}
                      //onMouseOut={(e) => alert(e.currentTarget.innerText)}
                  />
              </div>
          );
      };
      
      export { SearchInputBox };
      

      渲染函数

      const renderInput = (inputProps: InputProps<ISuggestion>): React.ReactNode => {
          return <SearchInputBox loading={false} onChange={inputProps.onChange} placeHolder={inputProps.placeholder} searchIconName={'search'} {...inputProps.others} />;
      };
          
      

      【讨论】:

        【解决方案3】:

        我有同样的问题。

        我只需要将 HTMLElement 转换为 HTMLInputElement 如下所示

        const target = e.currentTarget as HTMLInputElement
        

        然后,当你这样做时它工作正常

        target.value
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-12-06
          • 2019-01-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-19
          相关资源
          最近更新 更多