[英]How to use usehook in a function using react and typescript?
[英]How to use the useHook in the component rather than passing the value returned from it as a prop to the components using react and typescript?
我想在組件本身中使用 useHook,而不是使用 react 和 typescript 將其作為道具傳遞給每個組件。
我想做什么? 我有一個名為 useRefresh 的 useHook,它返回 isLoading state。 This isLoading state 用於在每個頁面中顯示加載指示器。
所以我有三個頁面,只要這個 isLoading 為真,就應該在這些頁面中顯示一個加載指示器。
下面是我的代碼,
function App(){
const user = useGetUser();
return (
<Router>
<Switch>
<Route
path="/"
render={props: any => (
user ? (<Main {...props} />) : (
<LoginPage/>
);
)}
</Route>
</Switch>
</Router>
);
}
export function useLoad() {
const { refetch: refetchItems } = useGetItems();
const { refetch: refetchOwnedItems } = useListOwnedItems();
return async function() {
await refreshCompany();
refetchItems();
refetchOwnedItems();
};
}
function useAnother(Id: string) {
const [compId, setCompId] = React.useState(undefined);
const [isLoading, setIsLoading] = React.useState(false);
const comp = useCurrentComp(Id);
const load = useLoad();
if (comp && comp.id !== compId) {
setCompId(comp.id);
const prevCompId = compId !== undefined;
if (prevCompId) {
setIsLoading(true);
load().then(() => {
setIsLoading(false);
});
}
}
}
function Main ({user}: Props) {
useAnother(user.id);
return (
<Router>
<Switch>
<Route
path="/"
render={routeProps => (
<FirstComp {...routeProps} />
)}
/>
<Route
path="/items"
render={routeProps => (
<SecondComp {...routeProps} />
)}
/>
//many other routes like these
</Switch>
</Router>
);
}
function FirstComp () {
return(
<Wrapper>
//some jsx
</Wrapper>
);
}
function SecondComp () {
return(
<Wrapper>
//some jsx
</Wrapper>
);
}
現在我想將 isLoading state 傳遞給主要組件中的每個組件....所以我已經像下面一樣傳遞了它,
function Main ({user}: Props) {
const isLoading = useAnother(user.id); //fetching isLoading here from useHook
return (
<Router>
<Switch>
<Route
path="/"
render={routeProps => (
<FirstComp isLoading={isLoading} {...routeProps} />
)}
/>
<Route
path="/items"
render={routeProps => (
<SecondComp isLoading={isLoading} {...routeProps} />
)}
/>
//many other routes like these
</Switch>
</Router>
);
}
function FirstComp ({isLoading}: Props) {
return(
<Wrapper>
displayIndicatorWhen(isLoading);
//some jsx
</Wrapper>
);
}
function SecondComp ({isLoading}: Props) {
return(
<Wrapper>
displayIndicatorWhen(isLoading);
//some jsx
</Wrapper>
);
}
這行得通。 但對我來說似乎不是一個正確的方法.. 我不想通過這個 isLoading state 作為這些組件中的每一個的道具。 其中有10多個。
有沒有其他方法可以做到這一點。 有人可以幫我解決這個問題。 謝謝。
最常見的解決方案是創建一個包含整個組件樹的上下文。 此上下文包含您的鈎子拉入的 state
////LoadingContext.tsx
const LoadingContext = createContext();
const LoadingContextProvider = () => {
const [isLoading, setIsLoading] = useState(false);
return (
<LoadingContextProvider.Provider
value={{
isLoading,
setIsLoading
}}
/>
)
}
export const useLoading = () => useContext(LoadingContext);
您需要將上下文圍繞將調用useLoading
的任何內容:
import { LoadingContextProvider } from './LoadingContext' //or wherever this is relative to Main.tsx
<LoadingContextProvider>
<Router>
...(router stuff)
</Router>
</LoadingContextProvider>
現在您可以在較低級別的組件中調用 useLoading。
//in another file defining a lower-level component:
import { useLoading } from '../../LoadingContext' //or wherever the context stuff is relative to this component definition
const FirstComp = () =>
const [isLoading, setIsLoading] = useLoading();
const handleClick = () => {
setIsLoading(true);
callMyApi().then(() => setIsLoading(false));
}
if(isLoading){
return <LoadingGif />
}
else{
return <div onClick={handleClick}>Click me!</div>
}
)}
你想在這里完成的是全局 state。 有很多方法可以做到,但我認為最簡單的是原生的 React Context API。
您所要做的就是創建一個ContextProvider
,然后在組件中使用useContext
掛鈎來訪問它提供的值。
這是一個適用於您的案例的示例:
主.js
export const LoadingContext = React.createContext(true); //creating and exporting the context
function Main ({user}: Props) {
const isLoading = useAnother(user.id); //fetching isLoading here from useHook
return (
<LoadingContext.Provider value={isLoading}> {/* providing the value to the children */}
<Router>
<Switch>
<Route
path="/"
render={routeProps => (
<FirstComp {...routeProps} />
)}
/>
<Route
path="/items"
render={routeProps => (
<SecondComp {...routeProps} />
)}
/>
//many other routes like these
</Switch>
</Router>
</LoadingContext.Provider>
);
}
export default Main;
其他組件
import {LoadingContext} from './Main.js'
function FirstComp ({}: Props) {
const isLoading = useContext(LoadingContext); //accessing the value
return(
<Wrapper>
displayIndicatorWhen(isLoading);
//some jsx
</Wrapper>
);
}
function SecondComp ({}: Props) {
const isLoading = useContext(LoadingContext); //accessing the value
return(
<Wrapper>
displayIndicatorWhen(isLoading);
//some jsx
</Wrapper>
);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.