【问题标题】:'AuthProvider' cannot be used as a JSX component'AuthProvider' 不能用作 JSX 组件
【发布时间】:2021-01-22 22:26:04
【问题描述】:

我尝试在 Context Provider 中进行身份验证流程,但在使用 TypeScript 时遇到了问题。 这是Provider代码的问题片段:

interface AuthUserProviderProps {
  children?: React.ReactNode 
}

interface AuthUserInterface {
  token: string;
  setToken: (value: string) => void;
  loggedIn: boolean;
  };
  setBrand: (value: {}) => void;
}

export const authUser = createContext<AuthUserInterface | null >(null);

const AuthUserProvider = ({ children }: AuthUserProviderProps) => {

if (accessTokenVAR() && !jwtToken?.roles.toString().includes('admin')) {
  return isBrowser ? window.location.replace('www.somewhere.com') : ''
}

  return (
    <authUser.Provider
      value={{
        token,
        setToken,
        loggedIn,
      }}
    >
      { children}
    </authUser.Provider>
  );
};

export default AuthUserProvider;

App.tsx

export default function App({ Component, pageProps }: AppProps) {
  const apolloClient = useApollo(pageProps.initialApolloState);
  return (
    <ThemeProvider theme={TifTheme}>
      <AuthUserProvider>                      <===This line throws error
        <ApolloProvider client={apolloClient} >
          <CssBaseline />
          <Component {...pageProps} />
        </ApolloProvider>
      </AuthUserProvider>
    </ThemeProvider>
  );
}

错误是“AuthUserProvider”不能用作 JSX 组件。它的返回类型 'void | "" | Element' 不是有效的 JSX 元素。类型“void”不可分配给类型“Element”。它是由返回重定向引起的。 但我不知道如何处理这个错误

【问题讨论】:

    标签: reactjs typescript types react-context


    【解决方案1】:

    您的分析应该是正确的,是“重定向”的返回。您可以使用 React.FunctionComponent 轻松键入 React 功能组件的属性。

    我建议编写一个小的 useAccess 钩子并使用它来获取布尔值以用于显示原因或使用 useEffect 重定向用户。当您重定向到不同的页面时,组件返回的内容无关紧要。 所以我修改了你的代码,我做了一些更改并添加了 cmets,如果有帮助,请告诉我。

    import { createContext, FunctionComponent, useEffect, useMemo } from "react";
    
    interface AuthUserInterface {
      token: string;
      setToken: (value: string) => void;
      loggedIn: boolean;
      setBrand: (value: any) => void;
    }
    
    const AuthUser = createContext<AuthUserInterface | null>(null);
    
    const useAccess = (isBrowser: boolean) => {
      const hasAccess = useMemo(
        () => accessTokenVAR() && !jwtToken?.roles.toString().includes("admin"),
        // TODO: check if that's correct, these variables were not in your answer,
        // might need to add/pass them to the hook
        [accessTokenVAR, jwtToken]
      );
    
      useEffect(() => {
        // redirect here if has
        if (hasAccess && isBrowser) window.location.replace("www.somewhere.com");
      }, [isBrowser, hasAccess]);
    
      return hasAccess;
    };
    
    interface AuthUserProviderProps {
      isBrowser: boolean;
    }
    
    const AuthUserProvider: FunctionComponent<AuthUserProviderProps> = ({
      children,
      isBrowser
    }) => {
      const hasAccess = useAccess(isBrowser);
    
      return (
        <>
          {!hasAccess && <p>"No access"</p>}
          {hasAccess && (
            <AuthUser.Provider
              value={{
                // TODO: values not in question, where do they come from
                token,
                setToken,
                loggedIn
              }}
            >
              {children}
            </AuthUser.Provider>
          )}
        </>
      );
    };
    
    export { AuthUserProvider as default, AuthUser };
    

    【讨论】:

    • 谢谢,朱利安!我通过只用片段标签包装重定向来解决这个问题。但是您创建具有所有访问权限逻辑的挂钩的解决方案肯定更好,因此将以这种方式修改我的代码。
    猜你喜欢
    • 2021-06-02
    • 2022-06-20
    • 2021-02-20
    • 2021-09-13
    • 2022-08-22
    • 2022-06-11
    • 2022-06-14
    • 2022-10-21
    • 2022-06-15
    相关资源
    最近更新 更多