React Hook“useRef”无法在回调错误中调用

问题描述 投票:0回答:4

我正在尝试编写用于滚动到功能的 Reactjs 代码。我希望为“标签”数组的元素生成不同部分的引用 ID。

import { useRef } from 'react';

const useDivRefs = (labels) => {
  const divRefs = {};

  labels.forEach((label, i) => {
    const targetId = label.replace(/\s+/g, '');
    const ref = useRef(null); 
    divRefs[targetId] = ref;
  });

  return divRefs;
};

const MyComponent = () => {
  const labels = [
    'div 1',
    'div 2',
    'div 3',
  ];

  const divRefs = useDivRefs(labels);

  console.log('divRefs = ', divRefs);

 
  return divRefs; 
};

它可以工作,但是“const ref = useRef(null);”行显示以下错误

“React Hook“useRef”不能在回调内部调用。React Hooks 必须在 React 函数组件或自定义 React Hook 函数react-hooks/rules-of-hooks 中调用”

我怎样才能摆脱这个错误? 任何帮助将不胜感激。

javascript node.js reactjs react-hooks
4个回答
4
投票

React hooks 很特别。您只能将 React hooks 调用为 React 函数组件或自定义 hooks 中的顶级函数。

还可以查看 - https://legacy.reactjs.org/warnings/invalid-hook-call-warning.html

为了您的目的,您可以使用保存数组的

useRef

const divRefs = useRef([]);
...
   {items.map((item, i) => (
      <div 
          key={i} 
          ref={el => itemsRef.current[i] = el} >
        ...
      </div>
    ))}

1
投票

由于 React 处理钩子的方式,每个组件实例它们需要具有相同的确定性顺序。这就是为什么它们需要位于组件的顶层,或者位于其他钩子内。

因此,您无法安全地管理引用数组或引用对象(如果可能的话,还有很多其他复杂的情况如何工作)。

在类似的情况下,可以使用对数组的引用,或对对象的引用。

但是,你的案子似乎有点复杂:

const useDivRefs = (labels) => {
  const divRefs = useRef({});

  useEffect(() => {
    const tmp = {};
    labels.forEach((label, i) => {
      const targetId = label.replace(/\s+/g, ''); 
      tmp[targetId] = null;
    });
    divRefs.current = tmp;
  }, [labels]);

  return divRefs;
};

然后您可以像以前一样使用 ref 对象,只需添加额外的

.current


0
投票

React hooks,包括“useRef”,不能在功能组件顶层之外的任何块内调用。它们必须始终在功能组件主体内直接调用。


0
投票

可以像这样以编程方式创建引用:

const [refMapping, setRefMapping] = useState< { [key: string]: any }>({});

useEffect(() => {
  // Create a new array of refs whenever items change
  const refMapping = myList.reduce((prevVal, curVal) => {
    const newObject: any = { ...prevVal }
    newObject[curVal.key] = React.createRef()
    return newObject
  }, {})
  setRefMapping(refMapping);
}, [myList]);
© www.soinside.com 2019 - 2024. All rights reserved.