【问题标题】:Setting focus via a ref only works in setTimeout in React?通过 ref 设置焦点仅适用于 React 的 setTimeout?
【发布时间】:2019-03-14 08:27:17
【问题描述】:

我下面的代码可以工作,但如果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;

【问题讨论】:

  • 你有seen this issue吗?
  • @Tholle Ive 更新了我的问题。是的,我有,但随着 console.log 的工作,我认为我没有看到同样的问题。

标签: reactjs


【解决方案1】:

考虑到看似 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 将确保你的 ref 已经在 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>

【讨论】:

  • 我需要 componentDidUpdate 中的逻辑,以便仅在特定 url 更改后应用焦点。您的代码在组件首次渲染时没有应用焦点?
  • 是否删除了条件渲染帮助?
猜你喜欢
  • 1970-01-01
  • 2021-03-15
  • 1970-01-01
  • 1970-01-01
  • 2017-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-14
相关资源
最近更新 更多