我正在使用 useDimensions 钩子(Hook)来测量我的子组件并因此更新父组件(尽管这个问题也会发生在任何类似的测量钩子(Hook)上)。因此,我想为我拥有的每个子组件使用 useDimensions。然而,这是一个通用的父组件,可以接受任意数量的子组件,所以我必须遍历子组件并为每个子组件添加一个钩子(Hook)。

它目前看起来有点像这样:

import React from "react";
import useDimensions from "react-use-dimensions";

function Parent(props){
    const measurements = props.children.map(child => useDimensions());
    return props.children.map(
        (child, i) => React.cloneElement(child, {ref: measurements[i][0]})
    );
}

但是,这打破了 first rule of hooks : 不要在循环、条件或嵌套函数中调用 Hook。

在不违反 React 钩子(Hook)规则的情况下,这样做的最佳实践方法是什么?

最佳答案

hooks 规则的原因在 Why Do React Hooks Rely on Call Order 中有很好的解释。

如果需要总尺寸,而不需要单独测量每个 child ,那将很容易:

function Parent({children}) {
  const [ref] = useDimensions()
  return (
    <div ref={ref}>
      {children}
    </div>
  )
}

对于更复杂的场景,将 React 代码构建为多个组件是一种有效的方法,既不是“浪费时间”也不是“添加大量抽象”,例如:
function Parent({children}) {
  const measurements = useRef(Array(children.length))

  const createSetRef = (i) => (ref) => {
    measurements[i] = ref
  }

  return children.map(
    (child, i) => <Child setRef={createSetRef(i)}>{child}</Child>
  )
}

function Child({children, setRef}) {
  const [ref] = useDimensions()

  useEffect(() => setRef(ref), [])

  if (React.isValidElement(children)) {
    return React.cloneElement(children, {ref})
  } else {
    console.log("TODO:", children)
    return children
  }
}

关于reactjs - React hooks,每个 child 一个,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57238489/

10-11 12:56