【问题标题】:React focus useRef only working on refresh反应焦点 useRef 仅适用于刷新
【发布时间】:2022-06-14 21:24:21
【问题描述】:

我正在使用<NavLink /> 直接导航到特定组件。我认为这是问题所在 - 但问题是:

当路由完成并且组件呈现时,我试图让一个元素聚焦。我有一些工作的现有方法 - 滚动工作(即,我想要聚焦的元素靠近底部并且自动滚动工作。但是,焦点框不存在)。但是,当我刷新时,它会按需要工作 - 焦点具有滚动功能,并且元素周围有一个突出显示的框。

我不确定问题出在哪里,但我认为这是组件从 <NavLink /> 获取其初始渲染的事实。

这是我使用焦点的方式:

import React, { useEffect, useRef } from "react";

const Focus = () => {
  const focusRef = useRef(null);

  useEffect(() => {
    if (focusRef && focusRef.current) {
      focusRef.current.focus();
    }
  }, [focusRef.current]);

  return (
    <React.Fragment>
      <h1 tabIndex="-1" ref={focus}>
        Focus Here
      </h1>
    </React.Fragment>
  );
};

非常感谢任何帮助!

【问题讨论】:

    标签: javascript reactjs react-hooks


    【解决方案1】:

    您面临的问题是更改 ref 不会触发渲染。您正在使用 focusRef.current 作为 useEffect 钩子的依赖项,但实际上,当 focusRef 的当前值发生变化时,它不一定会触发效果,它只会改变 ref。那么你需要其他东西来触发重新渲染,当这种情况发生时,focusRef.current 的变化被检测到并且效果可以重新运行。如果focusRef.current 永远不会改变,那么该效果甚至只会在组件挂载时触发(这就是它在刷新时起作用的原因)。

    您可能使用了错误的工具来完成这项工作。问问自己你想要组件来响应什么。换位置?那么你需要一个基于位置变化的效果来运行,而不是参考。

    const focusRef = useRef()
    const location = useLocation()
    
    useEffect(() => {
      if (location.pathname === '/my-url') {
        focusRef.current.focus()
      }
    }, [location])
    

    这样的东西会触发location 的每次更改的效果,然后,在效果内部,您可以将条件放入例如路径名。

    【讨论】:

    • 这是关于路由器路径名的一个好点。谢谢你。我会试一试。如果我不能投票给你,我很抱歉,我没有足够的反馈。不过,我很感激你的时间。
    • 我试了一下,不幸的是,它似乎对我不起作用。
    • 对不起,不工作是一个太大的类别,如果你能更具体,我可以帮助更多;)
    • 对不起 - 它只是给了我与原始帖子相同的行为 - 焦点只会在刷新时起作用。
    【解决方案2】:

    引用是对具有单个属性的对象的引用 - current。设置当前属性不会改变对象,也不会导致重新渲染。

    为了避免这种情况,您可以使用useState 来保存引用。 react 中的 ref 也可以是一个函数。将setFocusRef 传递给组件,该组件将在渲染后立即调用它。这将设置focusRef 指向相关的DOM 元素,并导致重新渲染。 focusRef 的更改值将触发useEffect,由于focusRef 现在不是nullfocusRef.focus 将被调用。

    const { useState, useEffect } = React;
    
    const Focus = () => {
      const [focusRef, setFocusRef] = useState(null);
    
      useEffect(() => {
        if(!focusRef) return;
        
        focusRef.focus();
      }, [focusRef]);
    
      return (
        <h1 tabIndex="-1" ref={setFocusRef}>
          Focus Here
        </h1>
      );
    };
    
    ReactDOM.render(
      <Focus />,
      root
    )
    <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    
    <div id="root"></div>

    【讨论】:

    • 嗯。我似乎得到了同样的行为——不幸的是,重点只在刷新而不是在第一次渲染上。
    猜你喜欢
    • 2017-04-12
    • 2021-11-17
    • 1970-01-01
    • 1970-01-01
    • 2020-12-26
    • 2013-04-12
    • 1970-01-01
    • 2013-01-29
    • 1970-01-01
    相关资源
    最近更新 更多