Я создаю приложение React и работаю над аутентификацией пользователя. В настоящее время я использую BrowserRouter из 'react-router-dom' для управления маршрутизацией в своем приложении. У меня есть маршрут регистрации, и все остальные компоненты маршрутов заключены в функцию 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.info(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')
}
Обновлено: Я пришел к выводу, что проблема заключалась в синтаксисе объявления этого withAuth HOC, я обновил его следующим образом, и он загружается просто отлично. За исключением того момента, когда я использую "componentDidMount" для выполнения запроса graphql, HOC не выполняет компонентDidMount. 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} >
из render() внутри HOC.
javascript export const withAuth = (Component) => (props) => { ... withAuth принимает компонент, с помощью функции двойной стрелки я пытался извлечь реквизиты компонента, а затем, если пользователь аутентифицирован, передать их компоненту: javascript return ( <MyContext.Provider value = {data.me}> <Component {...props} /> </MyContext.Provider> ) Раньше я пробовал что-то вроде: javascript export const withAuth = (Component) => { return (props) => {...} } это все еще не работало.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Итак, после нескольких часов поиска я наконец смог найти решение моей проблемы выше.
Напомним, что я использовал react-router-dom для обработки маршрутизации в моем приложении от компонента SignIn до My Dashboard. Я добавил HOC ко всем другим компонентам маршрутов, ожидая, что компонент SignIn проверит, аутентифицирован ли пользователь; в противном случае пользователь был перенаправлен обратно в компонент SignIn.
Проблемы были следующие:
Решение:
A higher-order component is a function that takes a component and returns a new component.
Чтобы получить data.me:
Чтобы сделать запрос graphql с использованием apollo, необходимо иметь доступ к клиент.
Мне нужно было убедиться, что я передаю клиента из «ApolloProvider» с помощью «react-apollo» из корня.
Затем используйте Query из '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.info(error)
return (
<Redirect to = "/sign-in" />
);
}
return (
<MyContext.Provider value = {data.me}>
<Component {...this.props} />
</MyContext.Provider>
)
}}
</Query>
)
}
}
}
Каков синтаксис функции двойной стрелки? чего ты пытаешься этим добиться?