简体   繁体   English

如何在组件中使用 useHook,而不是将其返回的值作为 prop 传递给使用 react 和 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?

i want to use useHook within the component itself rather than passing it as a prop to each component using react and typescript.我想在组件本身中使用 useHook,而不是使用 react 和 typescript 将其作为道具传递给每个组件。

what i am trying to do?我想做什么? I have a useHook named useRefresh which returns isLoading state.我有一个名为 useRefresh 的 useHook,它返回 isLoading state。 This isLoading state is used to display a loading indicator in each of the pages. This isLoading state 用于在每个页面中显示加载指示器。

so i have three pages and whenever this isLoading is true should display a loading indicator in these pages.所以我有三个页面,只要这个 isLoading 为真,就应该在这些页面中显示一个加载指示器。

below is my code,下面是我的代码,

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>
    );
}

Now i want to pass isLoading state to each of the components in Main component....so i have passed it like below,现在我想将 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>
    );
}

This works.这行得通。 but doesnt seem like a right approach to me.. i dont want to pass this isLoading state as a prop to each of these components.但对我来说似乎不是一个正确的方法.. 我不想通过这个 isLoading state 作为这些组件中的每一个的道具。 there are more than 10 of them.其中有10多个。

is there someway that i can do it other way than this.有没有其他方法可以做到这一点。 could someone help me with this.有人可以帮我解决这个问题。 thanks.谢谢。

The most common solution is to create a context that wraps the entire tree of components.最常见的解决方案是创建一个包含整个组件树的上下文。 This context holds the state that your hook pulls in此上下文包含您的钩子拉入的 state

////LoadingContext.tsx
const LoadingContext =  createContext();

const LoadingContextProvider = () => {
    const [isLoading, setIsLoading] = useState(false);

    return (
        <LoadingContextProvider.Provider
            value={{
               isLoading,
               setIsLoading
            }}
        />
    )

}

export const useLoading = () => useContext(LoadingContext);

You need to wrap the context around anything that will be calling useLoading :您需要将上下文围绕将调用useLoading的任何内容:

import { LoadingContextProvider } from './LoadingContext' //or wherever this is relative to Main.tsx 

<LoadingContextProvider>
    <Router>
       ...(router stuff)
    </Router>
</LoadingContextProvider>

Now you can call useLoading in your lower-level components.现在您可以在较低级别的组件中调用 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>
    }
)}

What you would like to accomplish here is called global state.你想在这里完成的是全局 state。 There are many ways to do it, but I think the simplest is the native React Context API.有很多方法可以做到,但我认为最简单的是原生的 React Context API。

All you have to do is create a ContextProvider and then use the useContext hook inside your components to access the values it provides.您所要做的就是创建一个ContextProvider ,然后在组件中使用useContext挂钩来访问它提供的值。

Here is an example that should work for your case:这是一个适用于您的案例的示例:

Main.js主.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;

Other components其他组件

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.

相关问题 如何使用 react 和 typescript 在 function 中使用 usehook? - How to use usehook in a function using react and typescript? 如何使用打字稿中的枚举作为反应组件的默认道具值 - How to use an enum in typescript as a default prop value for a react component 如何修改代码以便可以使用 react 和 typescript 调用 usehook? - How to modify the code such that can call usehook using react and typescript? Prop TypeScript React 组件错误,使用样式化组件 - Prop TypeScript Error With React Component, Using Styled-Components 如何使用 React 和 typescript 将 prop 传递给组件? - How to pass prop to a component using React and typescript? Typescript - 限制将有效道具传递给 React 组件 - Typescript - Restrict passing valid prop to a React component React TypeScript HoC - 将组件作为道具传递 - React TypeScript HoC - passing Component as the prop Typescript React/styled-components - 将 function 作为组件传递给组件会在缺少类型时引发错误 - Typescript React/ styled-components - passing function as prop to component throws error on missing type 将 function 作为道具传递给 Typescript 反应功能组件 - Passing a function as a prop to a Typescript React Functional Component Typescript React/Nextjs styled-components - 将函数作为道具传递给组件会在缺少类型时引发错误 - Typescript React/Nextjs styled-components - passing function as prop to component throws error on missing type
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM