Как исправить «TypeError: Object(...) is not a function» при использовании функции переноса в React Component для аутентификации пользователя при входе в систему с помощью Browser Router

Я создаю приложение 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.

Каков синтаксис функции двойной стрелки? чего ты пытаешься этим добиться?

limido 09.06.2019 14:39
javascript export const withAuth = (Component) => (props) => { ... withAuth принимает компонент, с помощью функции двойной стрелки я пытался извлечь реквизиты компонента, а затем, если пользователь аутентифицирован, передать их компоненту: javascript return ( <MyContext.Provider value = {data.me}> <Component {...props} /> </MyContext.Provider> )
thisis-Shitanshu 09.06.2019 14:59

Раньше я пробовал что-то вроде: javascript export const withAuth = (Component) => { return (props) => {...} } это все еще не работало.

thisis-Shitanshu 09.06.2019 15:01
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
3
7 226
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Итак, после нескольких часов поиска я наконец смог найти решение моей проблемы выше.

Напомним, что я использовал react-router-dom для обработки маршрутизации в моем приложении от компонента SignIn до My Dashboard. Я добавил HOC ко всем другим компонентам маршрутов, ожидая, что компонент SignIn проверит, аутентифицирован ли пользователь; в противном случае пользователь был перенаправлен обратно в компонент SignIn.

Проблемы были следующие:

  1. Я получал TypeError: Object(...) не является функцией внутри моего HOC для проверки вошедшего в систему пользователя.
  2. Находясь внутри HOC, я не смог выполнить запрос graphql и получить data.me текущего пользователя.

Решение:

  • HOC TypeError: мой синтаксис был неправильным, я не возвращал компонент!

A higher-order component is a function that takes a component and returns a new component.

  • Чтобы получить data.me:

    1. Чтобы сделать запрос graphql с использованием apollo, необходимо иметь доступ к клиент.

    2. Мне нужно было убедиться, что я передаю клиента из «ApolloProvider» с помощью «react-apollo» из корня.

    3. Затем используйте 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>
            )
        }
    }
}

Другие вопросы по теме