You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让React Native的useMyHook同时支持两种调用返回方式?

实现支持两种调用方式的React Native自定义Hook

需求背景

我正在开发一个React Native库,希望自定义Hook useMyHook 支持两种调用方式:

  1. 直接获取show函数:const show = useMyHook()
  2. 解构获取show和hide函数:const {show, hide} = useMyHook()

这么做的核心原因是,当开发者仅需要show函数时,能直接自定义变量名(比如const showMyHookInBannerHomepage = useMyHook()),比解构重命名(const {show:showMyHookInBannerHomepage} = useMyHook())更简洁。

现有代码如下:

const useMyHook = () => {
  const MyCTX = useContext(MyContext);
  if (!MyCTX) {
    throw new Error('useMyHook must be defined.');
  }
  // 如何实现条件返回
  // return {show: MyCTX.show, hide:MyCTX.hide}
  // 同时支持
  // return MyCTX.show
  return MyCTX.show;
};

export default useMyHook;

可行方案

完全可以实现,这里提供两种实用方案:

方案一:给函数挂载属性

利用JavaScript中函数是一等对象的特性,直接把show函数作为返回值,同时给它挂载hide属性。这样既可以直接调用返回值作为show函数,也能通过解构获取show和hide:

const useMyHook = () => {
  const MyCTX = useContext(MyContext);
  if (!MyCTX) {
    throw new Error('useMyHook must be used within a MyContext provider.');
  }

  // 复用上下文里的show函数
  const show = MyCTX.show;
  // 给show函数挂载hide属性
  show.hide = MyCTX.hide;
  // 同时给show函数挂载自身作为show属性,满足解构需求
  show.show = show;

  return show;
};

export default useMyHook;

方案二:使用Proxy代理对象

创建包含show和hide的对象,通过Proxy让这个对象可以被当作函数调用(调用时执行show方法)。这种方式语义更清晰,返回值本质是对象,同时具备函数调用能力:

const useMyHook = () => {
  const MyCTX = useContext(MyContext);
  if (!MyCTX) {
    throw new Error('useMyHook must be used within a MyContext provider.');
  }

  const hookResult = {
    show: MyCTX.show,
    hide: MyCTX.hide
  };

  // 用Proxy实现对象的函数调用能力
  return new Proxy(hookResult, {
    apply(target, thisArg, args) {
      // 当被当作函数调用时,执行show方法
      return target.show(...args);
    }
  });
};

export default useMyHook;

方案对比

  • 方案一:代码简洁,无额外性能开销,但函数挂载属性的写法语义上稍显特殊。
  • 方案二:语义清晰,返回值本质是包含完整API的对象,同时支持函数式调用,兼容性上React Native的Hermes引擎完全支持Proxy。

内容的提问来源于stack exchange,提问作者flix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 15:27:41