我已经定义了如下上下文来设置状态,就像下面一样,
"[markdown]": {
"editor.wordWrap": "on",
"editor.wrappingIndent": "indent",
"editor.tabSize": 2
},
我在如下两个组件Uploadbutton和userbutton中使用此上下文,
interface DialogsCtxState {
isDialogOpen: boolean;
setIsDialogOpen: React.Dispatch<React.SetStateAction<boolean>>;
itemVisible: boolean;
setItemVisible: React.Dispatch<React.SetStateAction<boolean>>;
}
const initialState: DialogsCtxState = {
isDialogOpen: false,
setIsDialogOpen: () => {},
itemVisible: false,
setItemVisible: () => {},
};
export const DialogsContext = React.createContext<
DialogsCtxState
>(initialState);
export const DialogsContextProvider: React.FC = ({ children }) => {
const [isDialogOpen, setIsDialogOpen] = React.useState<boolean>(
false
);
const [itemsVisible, setItemsVisible] = React.useState<boolean>(
false
);
return (
<DialogsContext.Provider
value={{
isDialogOpen,
setIsDialogOpen,
itemVisible,
setItemVisible,
}}
>
{children}
</DialogsContext.Provider>
);
};
以上代码片段效果很好。但是我想使用onUpload和onAdd方法将代码移到DialogContext文件中,其结果如下所示,
function UploadButton() {
const {isDialogOpen, setIsDialogOpen, itemVisible, setItemVisible} =
React.useContext(DialogContext);
const onUpload = () => {
itemVisible && setItemVisible(false);
setIsDialogOpen(isDialogOpen => !isDialogOpen);
}
return (
<Button onClick={onUpload}/>
);
}
function UserButton() {
const {isDialogOpen, setIsDialogOpen, itemVisible, setItemVisible} =
React.useContext(DialogContext);
const onAdd = () => {
isDialogOpen && setIsDialogOpen(false);
setItemVisible(prev => !prev);
}
return (
<Button onClick={onAdd}/>
);
}
我尝试过的,
在包含DialogContext的文件中,我尝试了以下类似操作
const onAdd = () => {
function1(); //where thiscontains the code in onAdd before snippet.
}
const onUpload = () => {
function2();//where this contains code in onUpload snippet before
}
但是我得到了错误react.usecontext用于一个既不是React函数组件也不是自定义react钩子的函数中。
我该如何解决。有人可以帮我解决这个问题。谢谢。
答案 0 :(得分:0)
看起来从上下文返回的值的唯一用途是创建onUpload
和onAdd
函数。在DialogsContextProvider
组件中创建函数以将其作为值传递是一种更好的方法。例子
// context
interface DialogsCtxState {
onUpload: () => void;
onAdd: () => void;
};
const initialState: DialogsCtxState = {
onUpload: () => {},
onAdd: () => {}
};
export const DialogsContext = React.createContext<
DialogsCtxState
>(initialState);
DialogsContextProvider
组件
// context provider
export const DialogsContextProvider: React.FC = ({ children }) => {
const [isDialogOpen, setIsDialogOpen] = React.useState<boolean>(
false
);
const [itemsVisible, setItemsVisible] = React.useState<boolean>(
false
);
// onUpload function
const onUpload = useCallback(() => {
itemsVisible && setItemsVisible(false);
setIsDialogOpen((isDialogOpen) => !isDialogOpen);
}, [itemsVisible]);
// onAdd function
const onAdd = useCallback(() => {
isDialogOpen && setIsDialogOpen(false);
setItemsVisible((prev) => !prev);
}, [isDialogOpen]);
return (
<DialogsContext.Provider value={{ onAdd, onUpload}}>
{children}
</DialogsContext.Provider>
);
};
这就是如何在UploadButton
和UserButton
组件中使用它的方法,
const UserButton: React.FC = () => {
const { onAdd } = React.useContext(DialogsContext)
// rest of the logic
}
const UploadButton: React.FC = () => {
const { onUpload } = React.useContext(DialogsContext)
// rest of the logic
}
注意,您的代码中存在多种错别字,因此如果您忽略采用自定义函数方法时发生的错误,因为useContext
仅可用于功能组件< / strong>和自定义挂钩。要解决此问题,您必须采用自定义挂钩方法。例如
export const useOnUpload = () => {
const { isDialogOpen, setIsDialogOpen, itemsVisible, setItemsVisible,
} = React.useContext(DialogsContext);
const onUpload = useCallback(() => {
itemsVisible && setItemsVisible(false);
setIsDialogOpen((isDialogOpen) => !isDialogOpen);
}, [itemsVisible, setIsDialogOpen, setItemsVisible]);
return onUpload;
};
// usage
function UploadButton() {
const onUpload = useOnUpload();
// rest of the logic
}
// similarly you can create the onUseAdd hook