How to fix "TypeError: Object(...) is not a function" when using a wrap function on React Component to authenticate user login with Browser Router
How to fix "TypeError: Object(...) is not a function" when using a wrap function on React Component to authenticate user login with Browser Router
我正在构建一个 React 应用程序并处理它的用户身份验证。
目前我正在使用 'react-router-dom' 的 BrowserRouter 来管理我的应用程序中的路由。
我有一个注册路线,所有其他路线组件都包装在一个函数 'withAuth' 中。
'withAuth' 的作用是查看应用程序是否已通过身份验证。如果用户已通过身份验证,则应加载该组件(此处有问题!),否则应将其重定向到登录组件(工作正常!)。
登录后,当应用程序重定向到组件包含在 'withAuth' 函数中的路径时。我收到以下错误:
TypeError: Object(...) is not a function
(anonymous function)
F:/Projects/beyouplus/beyouplus/beyouplus-client/src/services/auth.service.js:14
11 | return useContext(MyContext)
12 | }
13 |
>14 | export const withAuth = (Component) => (props) => {
15 | if (!isSignedIn()) {
16 | if (props.history.location.pathname === '/sign-in') {
17 | return null
我的App.js:
import React from 'react';
import {
BrowserRouter,
Route,
Redirect
} from 'react-router-dom'
// Import Screens
import SignInScreen from './components/SignInScreen'
import DepartmentScreen from './components/DepartmentScreen'
// Import Services
import { withAuth } from './services/auth.service'
const App = () => (
<BrowserRouter>
<Route exact path="/sign-in" component={SignInScreen}/>
<Route exact path="/dept" component={withAuth(DepartmentScreen)}/>
<Route exact path="/" render={redirectToDept} />
</BrowserRouter>
)
const redirectToDept = () => (
<Redirect to="/dept" />
)
export default App;
auth.service.js 文件:
import React, { useContext } from 'react'
import { Redirect } from 'react-router-dom'
import client from '../client'
import { getMeQuery } from '../graphql/queries'
import { useCacheService } from './cache.service'
const MyContext = React.createContext(null)
export const useMe = () => {
return useContext(MyContext)
}
export const withAuth = (Component) => (props) => {
if (!isSignedIn()) {
if (props.history.location.pathname === '/sign-in') {
return null
}
return (
<Redirect to="/sign-in" />
)
}
const { data, error, loading } = getMeQuery()
useCacheService()
if(loading) return null
if(error || !data.me) {
signOut()
return <Redirect to="/sign-in" />
}
console.log(data.me)
return (
<MyContext.Provider value={data.me}>
<Component {...props} />
</MyContext.Provider>
)
}
export const isSignedIn = () => {
//return /authToken=.+(;!$)/.test(document.cookie)
return document.cookie.includes('authToken')
}
编辑:
我发现问题出在用 Auth HOC 声明它的语法上,我用以下内容更新了它,它加载得很好。 除了现在我使用 "componentDidMount" 进行 graphql 查询时, HOC 不是 运行 "componentDidMount"。
auth.service.js
export const withAuth = (Component) => {
return class extends React.Component {
state = {
data: null
}
componentDidMount() {
if (!isSignedIn()) {
if (this.props.history.location.pathname === '/sign-in') {
return null;
}
return (
<Redirect to="/sign-in" />
);
}
const { data, error, loading } = getMeQuery;
useCacheService();
if (loading) return null;
if (data === undefined) return null;
if (error || !data.me) {
signOut();
return <Redirect to="/sign-in" />;
}
this.setState({
data
})
}
render() {
const { data } = this.state;
return (
<MyContext.Provider value={data.me}>
<Component {...this.props} />
</MyContext.Provider>
)
}
}
}
所以我得到了错误
TypeError: Cannot read property 'me' of null
/> 52 | < MyContext.Provider value={data.me} >
来自 HOC 中的 render()。
所以在搜索了几个小时之后,我终于找到了解决上述问题的方法。
回顾一下,我使用 react-router-dom 来处理我的应用程序中从登录组件到我的仪表板的路由。我向所有其他路由组件添加了一个 HOC,期望 SignIn 组件检查用户是否已通过身份验证;如果不是,则用户被路由回登录组件。
问题如下:
- 我收到一个 TypeError: Object(...) is not a function,在我的 HOC 中验证 logged-in 用户。
- 在 HOC 中,我无法进行 graphql 查询并获取当前用户的 data.me。
解决方法:
- HOC 类型错误:我的语法错误,我没有返回组件!
A higher-order component is a function that takes a component and returns a new component.
得到data.me:
要使用 apollo 进行 graphql 查询,需要访问 client.
我必须确保从 'ApolloProvider' 到 'react-apollo' 从根目录传递客户端。
比使用来自 'react-apollo' 的查询来查询 graphql 服务器,并处理数据、错误和加载。
这是我的新 auth.service!
export const withAuth = (Component) => {
return class extends React.Component {
render() {
if (!isSignedIn()) {
if (this.props.history.location.pathname === '/sign-in') {
return null;
}
return (
<Redirect to="/sign-in" />
);
}
useCacheService();
return (
<Query query={getMeQuery}>
{({ loading, error, data }) => {
if (loading) {
return (
<div>
Loading
</div>
);
}
if (error || !data.me) {
signOut();
console.log(error)
return (
<Redirect to="/sign-in" />
);
}
return (
<MyContext.Provider value={data.me}>
<Component {...this.props} />
</MyContext.Provider>
)
}}
</Query>
)
}
}
}
我正在构建一个 React 应用程序并处理它的用户身份验证。 目前我正在使用 'react-router-dom' 的 BrowserRouter 来管理我的应用程序中的路由。 我有一个注册路线,所有其他路线组件都包装在一个函数 'withAuth' 中。 'withAuth' 的作用是查看应用程序是否已通过身份验证。如果用户已通过身份验证,则应加载该组件(此处有问题!),否则应将其重定向到登录组件(工作正常!)。
登录后,当应用程序重定向到组件包含在 'withAuth' 函数中的路径时。我收到以下错误:
TypeError: Object(...) is not a function (anonymous function) F:/Projects/beyouplus/beyouplus/beyouplus-client/src/services/auth.service.js:14
11 | return useContext(MyContext)
12 | }
13 |
>14 | export const withAuth = (Component) => (props) => {
15 | if (!isSignedIn()) {
16 | if (props.history.location.pathname === '/sign-in') {
17 | return null
我的App.js:
import React from 'react';
import {
BrowserRouter,
Route,
Redirect
} from 'react-router-dom'
// Import Screens
import SignInScreen from './components/SignInScreen'
import DepartmentScreen from './components/DepartmentScreen'
// Import Services
import { withAuth } from './services/auth.service'
const App = () => (
<BrowserRouter>
<Route exact path="/sign-in" component={SignInScreen}/>
<Route exact path="/dept" component={withAuth(DepartmentScreen)}/>
<Route exact path="/" render={redirectToDept} />
</BrowserRouter>
)
const redirectToDept = () => (
<Redirect to="/dept" />
)
export default App;
auth.service.js 文件:
import React, { useContext } from 'react'
import { Redirect } from 'react-router-dom'
import client from '../client'
import { getMeQuery } from '../graphql/queries'
import { useCacheService } from './cache.service'
const MyContext = React.createContext(null)
export const useMe = () => {
return useContext(MyContext)
}
export const withAuth = (Component) => (props) => {
if (!isSignedIn()) {
if (props.history.location.pathname === '/sign-in') {
return null
}
return (
<Redirect to="/sign-in" />
)
}
const { data, error, loading } = getMeQuery()
useCacheService()
if(loading) return null
if(error || !data.me) {
signOut()
return <Redirect to="/sign-in" />
}
console.log(data.me)
return (
<MyContext.Provider value={data.me}>
<Component {...props} />
</MyContext.Provider>
)
}
export const isSignedIn = () => {
//return /authToken=.+(;!$)/.test(document.cookie)
return document.cookie.includes('authToken')
}
编辑: 我发现问题出在用 Auth HOC 声明它的语法上,我用以下内容更新了它,它加载得很好。 除了现在我使用 "componentDidMount" 进行 graphql 查询时, HOC 不是 运行 "componentDidMount"。 auth.service.js
export const withAuth = (Component) => {
return class extends React.Component {
state = {
data: null
}
componentDidMount() {
if (!isSignedIn()) {
if (this.props.history.location.pathname === '/sign-in') {
return null;
}
return (
<Redirect to="/sign-in" />
);
}
const { data, error, loading } = getMeQuery;
useCacheService();
if (loading) return null;
if (data === undefined) return null;
if (error || !data.me) {
signOut();
return <Redirect to="/sign-in" />;
}
this.setState({
data
})
}
render() {
const { data } = this.state;
return (
<MyContext.Provider value={data.me}>
<Component {...this.props} />
</MyContext.Provider>
)
}
}
}
所以我得到了错误
TypeError: Cannot read property 'me' of null
/> 52 | < MyContext.Provider value={data.me} >
来自 HOC 中的 render()。
所以在搜索了几个小时之后,我终于找到了解决上述问题的方法。
回顾一下,我使用 react-router-dom 来处理我的应用程序中从登录组件到我的仪表板的路由。我向所有其他路由组件添加了一个 HOC,期望 SignIn 组件检查用户是否已通过身份验证;如果不是,则用户被路由回登录组件。
问题如下:
- 我收到一个 TypeError: Object(...) is not a function,在我的 HOC 中验证 logged-in 用户。
- 在 HOC 中,我无法进行 graphql 查询并获取当前用户的 data.me。
解决方法:
- HOC 类型错误:我的语法错误,我没有返回组件!
A higher-order component is a function that takes a component and returns a new component.
得到data.me:
要使用 apollo 进行 graphql 查询,需要访问 client.
我必须确保从 'ApolloProvider' 到 'react-apollo' 从根目录传递客户端。
比使用来自 'react-apollo' 的查询来查询 graphql 服务器,并处理数据、错误和加载。
这是我的新 auth.service!
export const withAuth = (Component) => {
return class extends React.Component {
render() {
if (!isSignedIn()) {
if (this.props.history.location.pathname === '/sign-in') {
return null;
}
return (
<Redirect to="/sign-in" />
);
}
useCacheService();
return (
<Query query={getMeQuery}>
{({ loading, error, data }) => {
if (loading) {
return (
<div>
Loading
</div>
);
}
if (error || !data.me) {
signOut();
console.log(error)
return (
<Redirect to="/sign-in" />
);
}
return (
<MyContext.Provider value={data.me}>
<Component {...this.props} />
</MyContext.Provider>
)
}}
</Query>
)
}
}
}