![](/img/trans.png)
[英]How to use hooks as value of context provider in react js typescript
[英]How to properly use React Context Provider with Typescript?
我已经持续了好几个小时试图寻找我认为可行但无法做到的东西。 你能帮我解决这个问题吗?
我在这里有我的文件浏览器上下文,我想将文件夹数据传递给另一个 function。
import { createContext, useContext } from 'react';
export interface fileBrowserContext {
folderData: string;
}
export const FileBrowserContext = createContext<fileBrowserContext>({
folderData: '',
});
export const useFileBrowserContext = () => useContext(FileBrowserContext);
这是我使用它的组件。 我还使用了 react-hook-form,当我单击提交按钮时它正在工作。
const FileBrowser = () => {
const { control, watch, handleSubmit, register, reset, errors } = useForm({
reValidateMode: 'onChange',
defaultValues: {
createFolder: '',
},
});
const [folderData, setFolderData] = useState<string>('');
async function onSubmit(formData: any) {
if (Object.keys(errors).length === 0) {
/* Create folder */
setFolderData(formData.createFolder);
reset({ createFolder: '' });
}
handleToastSuccess({
message: 'Folder Created',
});
}
function renderForm() {
return (
<Form onSubmit={handleSubmit(onSubmit)} className="CreateFolderForm">
<Form.Group>
<Form.Label>Create Folder</Form.Label>
<Form.Control
id="createFolder"
name="createFolder"
ref={register({
required: {
value: true,
message: 'This field is required.',
},
})}
/>
</Form.Group>
<Button
variant="contained"
color="primary"
type="submit"
>
Create
</Button>
</Form>
);
}
const {
isCreateFolderOpen,
setIsCreateFolderOpen,
handleFileCallback,
} = useFileActionHandler(
createFolder,
);
return (
<FileBrowserContext.Provider value={{ folderData: folderData }}>
<>
<h1> File Browser </h1>
{folderData + ','}
</>
<CustomModal
showModal={isCreateFolderOpen}
setShowModal={setIsCreateFolderOpen}
modalHeading="Create Folder"
modalContent={renderForm()}
/>
</FileBrowserContext.Provider>
)
}
我正在 utils.tsx 上调用我的 useFileBrowserContext()。 我需要上面组件中的 folderData,我打算在其中使用上下文调用该组件,以便能够将文件夹保存在我正在使用的 Chonky 库中。
export const useFileActionHandler = (
setCurrentFolderId: (folderId: string) => void,
createFolder: (folderName: string) => void,
) => {
const [isCreateFolderOpen, setIsCreateFolderOpen] = useState<boolean>(false);
const { folderData } = useFileBrowserContext();
const handleFileCallback = useCallback(
(data: ChonkyFileActionData) => {
if (data.id === ChonkyActions.CreateFolder.id) {
// CONTEXT BEING CALLED HERE
setIsCreateFolderOpen(true);
if (folderData) createFolder(folderData);
}
console.log('file browser', folderData);
},
[
createFolder,
],
);
return {
handleFileCallback,
isCreateFolderOpen,
setIsCreateFolderOpen,
};
};
我的控制台中没有错误,但行为是当我在 utils.tsx 中控制台记录 folderData 时,它返回一个空字符串,我认为这意味着从组件传递的 folderData 不起作用。 提前感谢您的帮助。
为了让组件使用useContext
,它们必须是Context.Provider
的后代。 在您的情况下,您尝试在FileBrowser
组件中使用FileBrowserContext
,但它不是Context.Provider
的后代,因此它接收folderData
的默认值(空字符串)。
所以,目前你有:
<App>
<FileBrowser>
<FileBrowserContext.Provider>
{/* ... */}
</FileBrowserContext.Provider>
</FileBrowser>
</App>
但你需要
<App>
<FileBrowserContext.Provider>
<FileBrowser>
{/* ... */}
</FileBrowser>
</FileBrowserContext.Provider>
</App>
解决方法是将您的Context.Provider
组件向上移动一个级别并将其呈现为FileBrowser
的父级,而不是让FileBrowser
本身呈现它。 您可以将其包装到一个自定义组件中,该组件处理设置正确的value
,如下所示:
const FileBrowserContextProvider = () => {
const [folderData, setFolderData] = useState('');
return (
<FileBrowserContext.Provider value={{ folderData, setFolderData }}>
{children}
</FileBrowserContext.Provider>
);
};
const App = () => {
return (
<FileBrowserContextProvider>
<FileBrowser /> {/* <-- now FileBrowser can safely useContext
since it's a descendent of the Provider */}
</FileBrowserContextProvider>
);
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.