解决:使用自定义输入组件时,React-day-picker Daypicker输入失去焦点

时间:2019-09-26 09:39:03

标签: javascript reactjs react-day-picker

工作沙箱为https://codesandbox.io/s/react-day-picker-base-h9fv6

我一直在尝试实现简单的日期选择器输入,您既可以在输入字段中输入日期,又可以在选择器中进行选择。

问题是当我使用自定义输入时, <DayPickerInput component ={CustomInput}.../>,使用选择器时输入失去焦点。没有自定义输入就不会发生这种情况。在文档中说

  

“如果要在用户选择某天时保持焦点,则组件类必须具有focus方法。”

但是我不确定应该如何实现。

2 个答案:

答案 0 :(得分:1)

如果您需要一个带有焦点方法的自定义组件,我认为您需要使用一个类组件,以及refs

class Input extends React.Component {
  constructor(props) {
    super(props);
    this.inputRef = React.createRef();
  }

  focus() {
    this.inputRef.current.focus();
  }

  render() {
    return <input {...this.props} ref={this.inputRef}/>
  }
}

答案 1 :(得分:0)

我使用来自“react-text-mask”库的 MaskedInput 组件,以及来自“”的“带有两个输入的日期范围选择器”的自定义叠加组件 react-day-picker'。

自定义叠加和输入:

const renderMaskedInput = (_props, _ref) => {
        return (
           <MaskedInput
             mask={getLocaleMask}
             showMask
             ref={_ref}
             type="text"
             render={(ref, inputProps) => <input ref={ref} {...inputProps} />}
             {..._props}
      />
    );};


<DayPickerInput
   component={_props => renderMaskedInput(_props, startInputRef)}
   overlayComponent={_props => (
      <Popper
        open={Boolean(startAnchorEl)}
        anchorEl={startAnchorEl}
        style={{ zIndex: 10000 }}
      >
        <div {..._props} className={customOverlayWrapper}>
          <div className={customOverlay}>{_props.children}</div>
        </div>
      </Popper>
    )}

我的问题是在打开或点击自定义叠加时从选择器输入中失去焦点,并且“keepFocus”道具是不适用于自定义输入。因此,点击背景后会导致关闭叠加层出现问题,因为叠加层仅通过输入的“onBlur”关闭。

仅通过 onClick 或其他方式将焦点硬设置在输入上是行不通的。 我的解决方案是在自定义叠加层打开时更改输入引用后在useEffect中设置焦点,但这还不够,因为点击叠加层后焦点丢失,所以我们只是在3之后将焦点设置为输入DayPicker 的处理程序:onFocus、onMonthChange、onCaptionChange(参见代码和框示例)。

并且使用 Popper 作为 DayPickerInput 的自定义叠加层解决了在屏幕上的空闲区域渲染叠加层的问题(叠加层的自动定位)。此外,Popper 与 Portal 配合使用,它解决了渲染叠加层的许多问题。

完整代码https://codesandbox.io/s/optimistic-glitter-c77gb

简短版本

    const focusStartInput = () => {
      startInputRef.current.inputElement.focus();
    }
    
    useEffect(() => {
    // used because 'keepFocus' prop from the library does not work with the custom 
    //   overlay or with the react-text-mask input
    
    if (startAnchorEl) {
      // if the start picker overlay is open
      focusStartInput(); // input loses focus after overlay opening,
                         // so just reset focus
    }

    if (endAnchorEl) {
      // if the end picker overlay is open
      focusEndInput(); // input loses focus after overlay opening, so just reset focus
    }
  }, [startAnchorEl, endAnchorEl]);

<DayPickerInput
   dayPickerProps={{ 
     onMonthChange: focusStartInput,
     onFocus: focusStartInput,
     onCaptionClick: focusStartInput,
   }}
   

主要问题的解决方案存在问题。如果我们没有点击日期选择器中的那一天(在标题、月份导航或其他地方),他的输入就会失去焦点。 我的代码有助于解决它