自动建议 renderInputComponent - 属性“onChange”的 inputProps 类型不兼容

Posted

技术标签:

【中文标题】自动建议 renderInputComponent - 属性“onChange”的 inputProps 类型不兼容【英文标题】:Autosuggest renderInputComponent - inputProps types of property 'onChange' are incompatible 【发布时间】: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 属性。

【问题讨论】:

【参考方案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

【讨论】:

以上是关于自动建议 renderInputComponent - 属性“onChange”的 inputProps 类型不兼容的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Selenium 从亚马逊上的自动建议中“点击”某些建议?

禁用自动建议

Ajax 自动完成(或自动建议)与 TAB 完成/自动填充类似于 shell 命令行完成?

Elasticsearch 自动完成或按令牌自动建议

如何在 GAE 中实现自动建议(自动完成)功能

如何在自动建议框中使用向下箭头键?