通过ref设置焦点仅在React的setTimeout中起作用?

时间:2019-03-14 08:27:18

标签: reactjs

下面的代码可以工作,但是如果this.buttonRef.current.firstChild.focus()不在setTimeout函数中,则它会停止工作。

从参考的官方文档中我看不到为什么发生这种情况。我的组件明显有问题吗?如果不是,我想知道我的网站上是否有其他组件在“窃取”焦点,就像url道具更改模式时那样。

更新:一件奇怪的事情是,如果我console.log在setTimeout之外,那么我可以看到DOM中存在该元素。

UPDATE2:原来是导致该问题的原因是我的模式中的React Trap Focus。移除聚焦陷阱意味着我不需要超时。因为我需要焦点陷阱,所以我认为setTimeout将需要保留。

https://github.com/davidtheclark/focus-trap-react

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

  componentDidUpdate(prevProps) {
    if (this.props.url === '' && prevProps.url = "old-url") {
      console.log('target element: ', this.buttonRef.current.firstChild)

      // This doenst work if not in a setTimeout
      // this.buttonRef.current.firstChild.focus();
      setTimeout(() => {
        this.buttonRef.current.firstChild.focus();
      }, 1);
    }
  }

  render() {
    const {
      limitIsReached,
        add
    } = this.props;

    return (
      <Fragment>
        <Title>My title</Title>
        <Section>
          <Button>
            Add a promo code
          </Button>
          <span ref={this.buttonRef}>
            {limitIsReached ? (
              <Alert
                message="Sorry limit reached"
              />
            ) : (
              <Button
                onClick={add}
              >
                Add new
              </Button>
            )}
          </span>

          <List compact />
        </Section>
      </Fragment>
    );
  }
}

export default MyComponent;

1 个答案:

答案 0 :(得分:0)

考虑到componentDidUpdate似乎在解析buttonRef之前就已运行,所以短的setTimeout并不是最糟糕的解决方案。

您可以尝试其他涉及设置状态的方法:

componentDidUpdate(prevProps) {
  if (.... oldurl) {
    this.setState({focusBtn: true})
  }

然后当buttonref解析时:

<span ref={ref=>{
  if (this.state.focusBtn) {
    this.buttonRef = ref;
    this.buttonRef.current.firstChild.focus();
  } } >...

编辑

好的,因此,如果您在渲染方法中删除条件,React将确保您的引用已在componentDidMount和componentDidUpdate上得到解析(如您所愿)

尝试一下:

<span ref={this.buttonRef}>

          <Alert
            message="Sorry limit reached"
            style={{display: limitIsReached ? 'block' : 'none'}}
          />

          <Button
            onClick={add} style={{display: limitIsReached ? 'none' : 'inline-block'}}
          >
            Add new
          </Button>
        )}
      </span>