在useEffect中使用订阅是否正确?

问题描述 投票:0回答:1

我目前正在开发一个 React 项目,我正在使用 useEffect 钩子来处理一些副作用。我遇到过一个场景,我需要订阅一些数据更改,我想知道在 useEffect 挂钩内使用订阅是否正确。

这是我正在尝试做的事情的简化版本:

import {useEffect, useState } from 'react';
import { Route, Routes } from 'react-router-dom';
import PrivateRoute from "./routes/PrivateRoute";
import  AuthProvider  from "./contexts/authContext";
import { Toaster } from 'react-hot-toast';
import SignIn from './pages/Authentication/SignIn';
import Loader from './common/Loader';
import ECommerce from './pages/Dashboard/ECommerce';
import routes from './routes';
import DefaultLayout from './layout/DefaultLayout';
import { authenticationService } from './contexts/authContext';


function App() {
  const [loading, setLoading] = useState<boolean>(true);
  const [currentUser, setCurrentUser] = useState(null);
  const [isAdmin, setIsAdmin] = useState(false);
  
  useEffect(() => {
    setTimeout(() => setLoading(false), 1000);

    const subscription = authenticationService.currentUser.subscribe(user => {
      setCurrentUser(user);
      setIsAdmin(user && user.role === 'admin');
      console.log(user)
    });

    return () => {
      subscription.unsubscribe();
    };
  }, []);

  return loading ? (
    <Loader />
  ) : (
    <>
    <AuthProvider>
      <Toaster
        position="top-right"
        reverseOrder={false}
        containerClassName="overflow-auto"
      />
      <Routes>
        <Route path="/login" element={<SignIn />}/>
        <Route element={<PrivateRoute />}>
        <Route path="/dashboard" element={<DefaultLayout />} >
            <Route index element={<ECommerce />} />
              {routes.map((routes, index) => {
            const { path, component: Component } = routes;
            return (
              <Route
                key={index}
                path={path}
                element={
                    <Component />
                }
              />
            );
          })}
          </Route>
        </Route>     
      </Routes>
      </AuthProvider>
    </>
  );
}

export default App;

authContext.tx

import { useContext, createContext, useState, ReactNode } from 'react';
import { useNavigate } from 'react-router-dom';
import { decodeToken } from "react-jwt";
import { BehaviorSubject } from 'rxjs';
import axios from 'axios';

const currentUserSubject = new BehaviorSubject(localStorage.getItem('currentUser') || '');
const AuthContext = createContext<any>(null);
const options = {
  method: 'POST',
  url: 'http://localhost:3000/login',
  data: null,
  headers: {
    'X-RapidAPI-Key': 'your-rapid-key',
    'X-RapidAPI-Host': 'famous-quotes4.p.rapidapi.com',
  },
};

const AuthProvider = ({ children }: { children: ReactNode }) => {
  const [user, setUser] = useState(null);
  const [token, setToken] = useState(localStorage.getItem('currentUser') ||'');
  const navigate = useNavigate();
  const loginAction = async (data: any) => {
    options.data = data;
    axios
      .request(options)
      .then(function ({ data }: { data: Response }) { 
        let dataDecoded = decodeToken(data.token);
        let userRetrieve : User = { username: '',role: ''};
        userRetrieve.username = dataDecoded.username;
        userRetrieve.role = dataDecoded.role;
        setUser(userRetrieve);
        setToken(data.token);
        currentUserSubject.next(userRetrieve);
      })
      .catch(function (error: any) {
        setUser(null);
        setToken('');
        currentUserSubject.next(null);
      });
  };
  const logOut = () => {
    setUser(null);
    setToken('');
    localStorage.removeItem('currentUser');
    currentUserSubject.next(null);
    navigate('/login');
  };
  return (
    <AuthContext.Provider value={{ token, user, loginAction, logOut }}>
      {children}
    </AuthContext.Provider>
  );
};

export const authenticationService = {
  currentUser: currentUserSubject.asObservable(),
  get currentUserValue () { return currentUserSubject.value }
};
export default AuthProvider;

export const useAuth = () => {
  return useContext(AuthContext);
};
reactjs react-hooks
1个回答
0
投票

我认为这看起来非常好。当组件被拆除以防止内存泄漏时,您将取消订阅,所以我认为您应该做好。我在组件中多次使用了相同的模式。

© www.soinside.com 2019 - 2024. All rights reserved.