{"record":{"id":"fef286f952ad539c","repo":"mihomo-party-org/clash-party","slug":"userules-must-be-used-within-an-rulesprovider","errorCode":null,"errorMessage":"useRules must be used within an RulesProvider","messagePattern":"useRules must be used within an RulesProvider","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/renderer/src/hooks/use-rules.tsx","lineNumber":34,"sourceCode":"  })\n\n  React.useEffect(() => {\n    const handler = (): void => {\n      mutate()\n    }\n    window.electron.ipcRenderer.on('rulesUpdated', handler)\n    return (): void => {\n      window.electron.ipcRenderer.removeListener('rulesUpdated', handler)\n    }\n  }, [mutate])\n\n  return <RulesContext.Provider value={{ rules, mutate }}>{children}</RulesContext.Provider>\n}\n\nexport const useRules = (): RulesContextType => {\n  const context = useContext(RulesContext)\n  if (context === undefined) {\n    throw new Error('useRules must be used within an RulesProvider')\n  }\n  return context\n}\n","sourceCodeStart":16,"sourceCodeEnd":38,"githubUrl":"https://github.com/mihomo-party-org/clash-party/blob/911e090537acdf7c50bee1c3aebecc2ef119a8b5/src/renderer/src/hooks/use-rules.tsx#L16-L38","documentation":"useRules consumes the Rules context (rules list plus a mutate function) and throws when no RulesProvider is present above the caller. The context defaults to undefined, and the hook converts that into an explicit error so the misuse is caught at the call site.","triggerScenarios":"Calling useRules() from a component not nested under <RulesContext.Provider> (rendered by RulesProvider); calling it from outside React render (event handlers registered at module scope, plain utility functions); rendering consumers in a detached React root such as tests.","commonSituations":"Provider placed inside a layout that some routes skip; consumers rendered in portals or dialogs attached to document.body but created from outside the tree; forgetting the wrapper in unit tests after extracting a component.","solutions":["Wrap consumers with <RulesProvider> (or move the provider up above the router/app root).","Ensure the provider stays mounted whenever consumers can render (guard consumers on the same condition as the provider).","In tests, supply RulesProvider (or a stub context provider) via the render wrapper option.","If a component must work with or without rules, accept rules via props instead of the hook at that level."],"exampleFix":"// before\nfunction RulesTable() {\n  const { rules, mutate } = useRules()\n  return <table>{rules.map(...)}</table>\n}\n// after\n<RulesProvider>\n  <RulesTable />\n</RulesProvider>","handlingStrategy":"validation","validationCode":"const context = React.useContext(RulesContext)\nif (context === undefined) {\n  return <RulesUnavailable />\n}","typeGuard":"function hasRulesContext(c: RulesContextType | undefined): c is RulesContextType {\n  return c !== undefined\n}","tryCatchPattern":null,"preventionTips":["Render RulesProvider above all components that call useRules, ideally at the app root.","Do not register event handlers at module scope that call useRules; call mutate via the hook inside components.","Keep provider and consumer mount conditions aligned (same guard variable).","Use a standard test wrapper with all providers for every component test."],"tags":["react","context","hooks"],"backgroundTag":"react-context-used-outside-provider","analyzedSha":"911e090537acdf7c50bee1c3aebecc2ef119a8b5","analyzedAt":"2026-08-30T13:00:49.174Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}