简体   繁体   English

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

[英]Solved: React-day-picker Daypicker Input loses focus when using custom input component

The working sandbox is https://codesandbox.io/s/react-day-picker-base-h9fv6工作沙箱是https://codesandbox.io/s/react-day-picker-base-h9fv6

I have been trying to implement a simple day picker input, where you can both enter the date in the input field and select in the picker.我一直在尝试实现一个简单的日期选择器输入,您既可以在输入字段中输入日期,也可以在选择器中输入 select。

The problem is that when I use a custom input, <DayPickerInput component ={CustomInput}.../> , the input loses focus when the picker is used.问题是,当我使用自定义输入<DayPickerInput component ={CustomInput}.../>时,使用选择器时输入会失去焦点。 This does not happen without a custom input.如果没有自定义输入,这不会发生。 In the docs it says在文档中它说

"If you want to keep the focus when the user picks a day, the component class must have a focus method." “如果要在用户选择一天时保持焦点,组件class必须有焦点方法。”

However I am not sure how I should implement this.但是我不确定我应该如何实现这一点。

If you need a custom component with a focus method, I think you need to use a class component, and refs :如果您需要具有焦点方法的自定义组件,我认为您需要使用class组件,并参考:

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}/>
  }
}

I use the MaskedInput component from " react-text-mask " library, and custom overlay component for 'Date Range picker with two inputs' from ' react-day-picker '.我使用“ react-text-mask ”库中的 MaskedInput 组件,以及来自“ react-day- picker”的“具有两个输入的日期范围选择器”的自定义覆盖组件

Custom overlay and input:自定义覆盖和输入:

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>
    )}

My problem was in losing focus from the picker input when opening or clicking on the custom overlay , and the ' keepFocus ' prop is did not work with custom input.我的问题是在打开或单击自定义覆盖时从选择器输入中失去焦点,并且“ keepFocus ”道具不适用于自定义输入。 So it causes problems with closing overlay after clicking on backdrop , because the overlay is closing only by 'onBlur' of input.因此,它会在单击背景后导致关闭叠加层出现问题,因为叠加层仅通过输入的“onBlur”关闭。

Just hard-setting focus on the input by onClick or something else did not work.只是硬设置专注于 onClick 或其他东西的输入是行不通的。 My solution is setting focus in useEffect after changing input ref when the custom overlay is opening, but it did not enough because the focus is losing after clicking on the overlay, so we just setting focus to input after 3 handlers of DayPicker : onFocus, onMonthChange, onCaptionChange (see codesandbox example).我的解决方案是在自定义覆盖打开时更改输入引用后在 useEffect 中设置焦点,但这还不够,因为单击覆盖后焦点丢失了,所以我们只是在DayPicker的 3 个处理程序之后将焦点设置为输入: onFocus、onMonthChange , onCaptionChange (参见代码框示例)。

And using Popper as a custom overlay for DayPickerInput solves a problem with rendering overlay in a free area at the screen (auto-positioning of overlay).并且使用Popper作为 DayPickerInput 的自定义覆盖解决了在屏幕上的空闲区域渲染覆盖的问题(覆盖的自动定位)。 Also, Popper works with Portal and it solves many problems with rendering overlay.此外,Popper 与 Portal 一起使用,它解决了渲染覆盖的许多问题。

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

Short version :短版

    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,
   }}
   

There is a problem with a solution from the main question .主要问题的解决方案存在问题 His input loses focus if we clicking not on the day in date picker (on the caption, month navigation, or somewhere else).如果我们不点击日期选择器中的日期(在标题、月份导航或其他地方),他的输入就会失去焦点。 My code helps to solve it .我的代码有助于解决它

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM