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

ReactJS中如何在独立函数中正确使用useContext?

解决方案:提取Context状态操作为可复用逻辑

问题原因拆解

  • 直接调用ChangeContent触发报错:useContext是React Hook,必须严格在组件或自定义Hook的顶层调用,普通函数里调用Hook会违反React的Hook规则,导致「Invalid hook call」错误。
  • 以组件形式调用无响应:onClick回调里返回组件JSX只是创建了一个React元素,并没有将其挂载到DOM中,组件内部的状态更新逻辑自然不会执行。

两种可行实现方案

方案1:封装为自定义Hook(推荐)

把所有Tab相关的状态操作整合到自定义Hook中,既遵守Hook规则,又能让组件轻松复用整套逻辑:

import React, { createContext, useState, useContext } from "react";

export const TabContext = createContext()

export default function App() {
  const [tabArray, setTabArray] = useState([{TabText:'Home' ,Selected:true}])

  return (
    <div className="App">
      <TabContext.Provider value= {{tabArray, setTabArray}}>
        <SideBar/>
        {tabArray.map((v,i) => <div key={i}>{v.TabText} </div>)}
      </TabContext.Provider>
    </div>
  );
}

// 自定义Hook:封装所有Tab操作逻辑
export function useTabActions() {
  const { tabArray, setTabArray } = useContext(TabContext);

  // 修改选中Tab的文本
  const changeContent = (text) => {
    setTabArray(oldValues => 
      oldValues.map(v => 
        v.Selected ? {...v, TabText: text} : {...v}
      )
    );
  };

  // 新增Tab(后续扩展的功能示例)
  const addTab = (newTabText) => {
    setTabArray(old => [...old, {TabText: newTabText, Selected: false}]);
  };

  // 删除Tab(后续扩展的功能示例)
  const deleteTab = (index) => {
    setTabArray(old => old.filter((_, i) => i !== index));
  };

  return { changeContent, addTab, deleteTab };
}

export function SideBar() {
  // 在组件内调用Hook,获取操作函数
  const { changeContent } = useTabActions();

  return (            
    <div>
      <button onClick={() => changeContent("All Commodity")}> All Commodity </button> 
    </div>
  )
}

方案2:封装为纯函数(轻量化选择)

如果只是单一逻辑的复用,也可以把状态更新逻辑写成纯函数,让组件在获取Context值后传入使用:

// 纯函数:只负责状态更新,不依赖Hook
export const changeTabContent = (setTabArray, text) => {
  setTabArray(oldValues => 
    oldValues.map(v => 
      v.Selected ? {...v, TabText: text} : {...v}
    )
  );
};

// 组件内使用
export function SideBar() {
  const { setTabArray } = useContext(TabContext);

  return (            
    <div>
      <button onClick={() => changeTabContent(setTabArray, "All Commodity")}> All Commodity </button> 
    </div>
  )
}

方案对比

  • 自定义Hook:适合整合多个相关操作,逻辑内聚性强,组件只需一次调用就能获取所有操作函数,后续扩展新功能更方便。
  • 纯函数:更轻量化,不需要遵守Hook规则,但需要组件手动传入Context中的状态更新函数,适合单一简单逻辑的复用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 02:50:16