reactjs - 自定义钩子(Hook)可以确定哪个组件调用它吗?

标签 reactjs react-hooks

我制作了一个自定义 Hook ,将数据注册到由使用它的组件键入的存储中,然后在卸载组件时从存储中删除数据。基本是这样的

const [id] = useState(Math.random());

const setData = useCallback((data) => {
  if(data) {
    setRegistrations({
      ...registrations,
      [id]: data
    });
  } else {
    const {[id]: _, ...nextRegistrations} = registrations;
    setRegistrations(nextRegistrations);
  }
}, [id]);

useEffect(() => {
  // update the registration if the data changed
  setData(data); 
}, [data, setData]);

useEffect(() => {
  // remove the registration on unmount
  setData();
}, []);

我正在使用 Math.random() 为使用我的钩子(Hook)的每个组件生成一个唯一的 id,效果很好,但我希望有一种方法可以找出该组件的名称正在使用我的钩子(Hook)的组件。如果我可以看到哪些数据是由哪个组件注册的,那么调试我的应用程序状态会更容易,但我所需要查看的只是一个随机小数。

现在我的商店看起来像这样

{
  '0.5694216823063629': { ... }
  '0.002760497537984463': { ... }
}

如果我能做这样的事情,我更愿意

{
  'MyComponent-1': { ... }
  'MyComponent-2': { ... }
  'MyOtherComponent-1': { ... }
}

是的,我知道我可以让组件传入一个键,但这没有捕获要点。我希望 API 保持纯净,不污染它,这样调试就更容易。

有没有办法找出哪个组件使用了我的钩子(Hook)?

最佳答案

函数和参数对象具有已弃用的属性,这些属性允许它们查看谁调用了它们 - Function.callerarguments.callee 。然而,它们在严格模式下都被阻止。

抛出错误时,您可以从堆栈中获取调用者的名称,但这很难看,您应该只在开发模式下使用它。这仅适用于函数组件,但由于您在钩子(Hook)中使用它,所以这不会成为问题。

示例(取自此 article ):

// taken from https://devimalplanet.com/javascript-how-to-get-the-caller-parent-functions-name
function whoIsMyDaddy() {
  try {
    throw new Error();
  } catch (e) {
    // matches this function, the caller and the parent
    const allMatches = e.stack.match(/(\w+)@|at (\w+) \(/g);
    // match parent function name
    const parentMatches = allMatches[2].match(/(\w+)@|at (\w+) \(/);
    // return only name
    return parentMatches[1] || parentMatches[2];
  }
}

const useDemo = () => {
  const daddy = whoIsMyDaddy()
  React.useEffect(() => console.log(daddy))
}

const ComponentX = () => {
  useDemo()
  
  return 'X'
}

const ComponentY = () => {
  useDemo()
  
  return 'Y'
}

ReactDOM.render(
  <div>
    <ComponentX />
    <ComponentY />
  </div>,
  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>

注意:使用 Math.random() 作为 id 并不是一个好主意,因为 Math.random() 并不是这样随机 - 请参阅此 answer 。您可以使用Crypto.getRandomValues()如果支持,或外部 uuid图书馆。

关于reactjs - 自定义钩子(Hook)可以确定哪个组件调用它吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66714408/

相关文章:

javascript - Redux 状态更改后 React 容器不会重新渲染

javascript - 如何防止子组件重新渲染?

reactjs - 仅重置 redux-from 中的一个向导

javascript - 无法访问文件上传的路径键

javascript - 如何不依赖 React/Webpack 3 应用程序中的相对路径

reactjs - React/Redux - 如何在 React 组件中显示 Redux 存储中的值?

reactjs - React Hook 在状态更改后不会重新渲染 array.map

reactjs - React 闭包中的 useState 值过时 - 如何修复?

javascript - 如何设置 useEffect 在第一次使用 eslint-react-hooks 渲染时从 API 获取数据?

reactjs - 我应该将组件中定义的所有函数包装在 useCallback 中吗?