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

React Context Provider存储的回调状态为undefined问题

问题描述

已查阅平台内其他开发者提出的同类问题,均未找到适配当前业务场景的解决方案。
项目包含公共布局组件,布局内置工具栏,负责触发表单提交、取消操作。为实现工具栏跨组件控制条件渲染表单的提交/取消逻辑,采用基于Context.Provider实现的FormProvider组件包裹整个布局,在Context状态变量中存储表单提交、取消的回调函数,逻辑如下:

  • 条件渲染加载的表单组件调用Context暴露的赋值方法,将表单提交/取消回调存入状态
  • 工具栏组件读取Context中的状态变量,调用对应回调执行操作

实际运行出现以下异常:

  • 从Context中读取到的存储回调的状态变量始终为undefined
  • 日志显示调用setOnSubmit方法赋值后,onSubmit值未按预期更新,监听onSubmit变化的useEffect钩子仅在首次渲染时触发
  • 点击工具栏保存按钮调用submit方法时,方法内部捕获的onSubmit值永远为undefined
业务代码片段

FormProvider

type FormContextProps = {
    setOnSubmit: (callable: Function | undefined) => void
    assignOnSubmit: Dispatch<any>
    setOnCancel: (callable: Function | undefined) => void
    submit: (e: any) => void
    cancel: () => void
}

const initAuthContextPropsState = {
    setOnSubmit: () => { },
    assignOnSubmit: () => { },
    setOnCancel: () => { },
    submit: (e: any) => { },
    cancel: () => { },
}

const FormContext = createContext<FormContextProps>(initAuthContextPropsState)

const useTForm = () => {
    return useContext(FormContext)
}

const FormProvider: FC = ({ children }) => {
    const [onSubmit, assignOnSubmit] = useState<Function | undefined>()
    const [onCancel, assignOnCancel] = useState<Function | undefined>()

    const setOnSubmit = (callable: Function | undefined) => {
        console.log('setOnSubmit', callable)
        assignOnSubmit(callable)
        console.log('setOnSubmit after', onSubmit)
    }

    const setOnCancel = (callable: Function | undefined) => {
        assignOnCancel(callable)
    }

    useEffect(() => {
        console.log("changed onSubmit"); // 该钩子仅在首次渲染时触发
    }, [onSubmit])

    const submit = (e: any) => {
        console.log('form submited', onSubmit) // 点击工具栏保存按钮时此处始终为undefined
        if (onSubmit) onSubmit(e)
    }

    const cancel = () => {
        if (onCancel) onCancel()
    }

    return (
        <FormContext.Provider value={{ setOnSubmit, assignOnSubmit, setOnCancel, submit, cancel }}>
            {children}
        </FormContext.Provider>
    )
}

Toolbar

const FormToolbar: FC = () => {
  const {classes} = useLayout()

  const {submit, cancel} = useTForm()

  const submitForm = (e: any) => submit(e)

  return (
    <div className='toolbar' id='kt_toolbar'>
      {/* begin::Container */}
      <div
        id='kt_toolbar_container'
        className={clsx(classes.toolbarContainer.join(' '), 'd-flex flex-stack')}
      >
        <DefaultTitle />

        {/* begin::Actions */}
        <div className='py-1 d-flex align-items-center'>
          
          {/* begin::Button */}
          <button
            className='btn btn-sm btn-primary me-4'
            onClick={submitForm}
          >
            Save
          </button>

          <button
            className='btn btn-sm btn-primary'
            onClick={cancel}
          >
            Cancel
          </button>
          {/* end::Button */}
        </div>
        {/* end::Actions */}
      </div>
      {/* end::Container */}
    </div>
  )
}

EditForm.tsx

const EditForm: React.FC<Props> = () = {
    const form = useRef() as React.MutableRefObject<HTMLFormElement>
    const { setOnSubmit, assignOnSubmit } = useTForm()

    useLayoutEffect(() => {
        setOnSubmit(() => { form?.current.dispatchEvent(new Event('submit')) });
        console.log('Form changed', form)
    }, [form])

    return (
        <form onSubmit={formik.handleSubmit} ref={form}>
            // ...
        </form>
    );
    
}

Main Component

function StaffManagement({ user, selectedLanguageId, idMenu }: Props) {

  const [editing, setEditing]: [any, Function] = useState(null)

  return (
    <div className='row'>
      <div className="col-lg-4">
        <ModuleItemList
          className='card-xxl-stretch mb-xl-3'
          edit={setEditing}
        />
      </div>
      <div className="col-lg-8">
        {editing && <EditForm
         userId={user.id}
         menuId={idMenu}
        />}
      </div>
    </div>
  )

}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 11:03:24