React useContext异常:confirmClear不是函数的问题解决
如何正确设置confirmClear函数?
我有一个React应用,需要实现可复用的确认对话框。其中的历史面板组件展示历史列表,并带有“清除历史”按钮,点击该按钮时我希望弹出确认对话框,但此时出现以下错误:
Uncaught (in promise) TypeError: confirmClear is not a function _callee$ HistoryPanel.js:18 Babel 2 node_modules main.js:133 Babel 2 node_modules main.js:35708 node_modules main.js:35697 handleClear HistoryPanel.js:17 React 14 unstable_runWithPriority scheduler.development.js:468 React 15 js index.js:6 Webpack 3
相关代码
HistoryPanel.js
import React from 'react' import { useHistory, useHistoryDispatch } from './HistoryProvider' import useConfirmDialog from "./ConfirmDialog" export default function HistoryPanel({formatting}) { const history = useHistory() const historyDispatcher = useHistoryDispatch() const confirmClear = useConfirmDialog() function display(entry) { return( <li key={entry.id}> <time dateTime={entry.id}>{new Intl.DateTimeFormat(formatting.locale, formatting.dateFormat).format(entry.id)}</time> {entry.entry} </li> ) } const handleClear = async () => { const ans = await confirmClear() if( ans ) { historyDispatcher({type: "clear"})} } function sorter(a,b) { return a.id - b.id } return( <section id="history"> <h1>History</h1> <button onClick={handleClear}>Clear History</button> <ul className="history"> { history.sort(sorter).map(display) } </ul> </section> ) }
ConfirmationDialog.js
import React, { createContext, useCallback, useContext, useRef, useState, } from 'react'; import Alert from "./Alert" const ConfirmDialog = createContext(); export function ConfirmDialogProvider({ children }) { const [state, setState] = useState({ isOpen: false }); const fn = useRef(); const confirm = useCallback( (data) => { return new Promise((resolve) => { setState({ ...data, isOpen: true }); fn.current = (choice) => { resolve(choice); setState({ isOpen: false }); }; }); }, [setState] ); return ( <ConfirmDialog.Provider value={confirm}> {children} <Alert {...state} onClose={() => fn.current(false)} onConfirm={() => fn.current(true)} /> </ConfirmDialog.Provider> ); } export default function useConfirmDialog() { return useContext(ConfirmDialog); }
问题分析与解决方案
核心问题
confirmClear is not a function错误的本质是**useConfirmDialog钩子未获取到有效函数**,原因是HistoryPanel组件不在ConfirmDialogProvider的上下文覆盖范围内。
解决步骤
在顶层组件包裹
ConfirmDialogProvider
必须在应用的顶层(如index.js或App.js)使用ConfirmDialogProvider包裹所有需要调用确认对话框的组件,示例代码:// index.js import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; import { ConfirmDialogProvider } from './ConfirmationDialog'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <ConfirmDialogProvider> <App /> </ConfirmDialogProvider> </React.StrictMode> );确认组件层级关系
确保HistoryPanel是ConfirmDialogProvider的后代组件,只有这样useContext(ConfirmDialog)才能拿到Provider提供的confirm函数。补充对话框参数(可选优化)
从ConfirmationDialog.js的代码来看,confirm函数支持传入data参数传递对话框的标题、内容等信息,可让提示更清晰:const handleClear = async () => { const ans = await confirmClear({ title: "确认清除历史", message: "确定要清空所有历史记录吗?此操作不可恢复。" }); if( ans ) { historyDispatcher({type: "clear"})} }此步骤需确保
Alert组件能接收并渲染这些属性。
验证
完成上述操作后,点击“清除历史”按钮时,confirmClear会正确返回Promise,对话框弹出后用户的选择会被正确解析,进而执行对应的清除操作。
内容的提问来源于stack exchange,提问作者Dean Brundage
相关产品推荐
相关产品推荐

