我正在嘗試創建一個自定義掛鉤,該掛鉤最終將在 NPM 上打包并在我作業的公司的專案內部使用。基本思想是我們希望包公開一個提供者,當掛載時,它會向服務器發出請求,該請求回傳一個權限字串陣列,然后通過背景關系提供給子組件。我們還需要一個can可以在提供程式中呼叫的函式,該函式將接受一個字串引數,并根據背景關系提供的權限陣列中是否存在該字串來回傳一個布林值。
我一直在關注這篇文章,但每當我can從提供者內部呼叫時,背景關系總是以未定義狀態回傳。下面是一個沒有功能的極其簡化的版本,我一直在嘗試弄清楚發生了什么:
useCan/src/index.js:
import React, { createContext, useContext, useEffect } from 'react';
type CanProviderProps = {children: React.ReactNode}
type Permissions = string[]
// Dummy data for fake API call
const mockPermissions: string[] = ["create", "click", "delete"]
const CanContext = createContext<Permissions | undefined>(undefined)
export const CanProvider = ({children}: CanProviderProps) => {
let permissions: Permissions | undefined
useEffect(() => {
permissions = mockPermissions
// This log displays the expected values
console.log("Mounted. Permissions: ", permissions)
}, [])
return <CanContext.Provider value={permissions}>{children}</CanContext.Provider>
}
export const can = (slug: string): boolean => {
const context = useContext(CanContext)
// This log always shows context as undefined
console.log(context)
// No functionality built to this yet. Just logging to see what's going on.
return true
}
然后是我正在測驗的簡單 React 應用程式:
useCan/example/src/App.tsx:
import React from 'react'
import { CanProvider, can } from 'use-can'
const App = () => {
return (
<CanProvider>
<div>
<h1>useCan Test</h1>
{/* Again, this log always shows undefined */}
{can("post")}
</div>
</CanProvider>
)
}
export default App
我哪里出錯了?這是我第一次真正使用 React 背景關系,所以我不確定在哪里查明問題所在。任何幫助,將不勝感激。謝謝。
uj5u.com熱心網友回復:
您應該使用state來管理權限。看下面的例子:
export const Provider: FC = ({ children }) => {
const [permissions, setPermissions] = useState<string[]>([]);
useEffect(() => {
// You can fetch remotely
// or do your async stuff here
retrivePermissions()
.then(setPermissions)
.catch(console.error);
}, []);
return (
<CanContext.Provider value={permissions}>{children}</CanContext.Provider>
);
};
export const useCan = () => {
const permissions = useContext(CanContext);
const can = useCallback(
(slug: string) => {
return permissions.some((p) => p === slug);
},
[permissions]
);
return { can };
};
使用useState您強制組件更新值。你可能想在這里閱讀更多
uj5u.com熱心網友回復:
你的實作有兩個問題:
- 在你的
CanProvider你重新分配的值permissions用=。這不會觸發 Provider 組件中的更新。我建議使用useState代替let和=。
const [permissions, setPermissions] = React.useState<Permissions | undefined>();
useEffect(() => {
setPermissions(mockPermissions)
}, []);
這將使 Provider 在permissions更改時正確更新。
- 您正在從常規函式(
can函式呼叫useContext)呼叫鉤子。這違反了 Hooks 的主要規則之一。您可以在此處了解更多資訊:https : //reactjs.org/docs/hooks-rules.html#only-call-hooks-from-react-functions
我建議創建一個自定義鉤子函式,為您提供所需的can功能。
像這樣的東西,例如
const useCan = () => {
const context = useContext(CanContext)
return () => {
console.log(context)
return true
}
}
然后,您應該在提供程式內部的某個組件的根級別(根據鉤子規則)使用全新的鉤子。例如,為內容提取一個組件,如下所示:
const Content = (): React.ReactElement => {
const can = useCan();
if(can("post")) {
return <>Yes, you can</>
}
return null;
}
export default function App() {
return (
<CanProvider>
<div>
<h1>useCan Test</h1>
<Content />
</div>
</CanProvider>
)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/396697.html
