refactor useSelector usage, use default userId everywhere

This commit is contained in:
martin-mfg
2025-11-23 14:26:19 +01:00
parent d1e5833b1a
commit a690478ef3
11 changed files with 85 additions and 55 deletions
+4 -5
View File
@@ -35,18 +35,17 @@ function createMockResponse(data, config) {
});
}
// store userId outside React context so the interceptor can access it
let userId = null;
// store isAuthenticated outside React context so the interceptor can access it
let isAuthenticated = null;
export function setUserId(newUserId) {
userId = newUserId;
export function setIsAuthenticated(newIsAuthenticated) {
isAuthenticated = newIsAuthenticated;
}
const defaultAdapter = getAdapter(axios.defaults.adapter);
// mock responses to unauthenticated "anuraghazra" requests
axios.defaults.adapter = async (config) => {
const isAuthenticated = userId && userId.length > 0;
if (isAuthenticated) {
return defaultAdapter(config);
}
+11 -10
View File
@@ -4,27 +4,29 @@
import React, { useEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import Skeleton from 'react-loading-skeleton';
import 'react-loading-skeleton/dist/skeleton.css';
import { createMockReq, createMockRes } from '../../mock-http';
import { default as router } from '../../backend/.vercel/output/functions/api.func/router.js';
import { setUserId } from '../../axios-override';
import { setIsAuthenticated } from '../../axios-override';
import {
useIsAuthenticated,
useUserToken,
} from '../../redux/selectors/userSelectors';
const SvgInline = (props) => {
const [svg, setSvg] = useState(null);
const [loaded, setLoaded] = useState(false);
const containerRef = useRef(null);
const userToken = useSelector((state) => state.user.token);
const userId = useSelector((state) => state.user.userId);
const userToken = useUserToken();
const isAuthenticated = useIsAuthenticated();
const { url } = props;
// provide userId to non-react code in axios-override.js
// provide isAuthenticated to non-react code in axios-override.js
useEffect(() => {
setUserId(userId);
}, [userId]);
setIsAuthenticated(isAuthenticated);
}, [isAuthenticated]);
useEffect(() => {
const loadSvg = async () => {
@@ -35,7 +37,6 @@ const SvgInline = (props) => {
let body;
let status;
const isAuthenticated = userId && userId.length > 0;
if (isAuthenticated && (!userToken || userToken === 'placeholderPAT')) {
// waiting for backend call to private-access
return;
@@ -67,7 +68,7 @@ const SvgInline = (props) => {
setLoaded(true);
};
loadSvg();
}, [userToken, userId, props.url]);
}, [userToken, isAuthenticated, props.url]);
useEffect(() => {
if (loaded && svg && containerRef.current) {
+8 -10
View File
@@ -1,12 +1,7 @@
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useDispatch } from 'react-redux';
import {
BrowserRouter as Router,
Route,
Routes,
useParams,
} from 'react-router-dom';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import {
logout as _logout,
setUserAccess as _setUserAccess,
@@ -20,11 +15,14 @@ import SettingsScreen from '../Settings';
import { NoMatchScreen } from '../Misc';
import { getUserMetadata } from '../../api';
import Footer from './Footer';
import {
useIsAuthenticated,
useUserKey,
} from '../../redux/selectors/userSelectors';
function App() {
const userId = useSelector((state) => state.user.userId);
const userKey = useSelector((state) => state.user.userKey);
const isAuthenticated = userId && userId.length > 0;
const userKey = useUserKey();
const isAuthenticated = useIsAuthenticated();
const dispatch = useDispatch();
const setUserAccess = (access) =>
+3 -3
View File
@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useDispatch } from 'react-redux';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
@@ -8,6 +8,7 @@ import { GiHamburgerMenu as HamburgerIcon } from 'react-icons/gi';
import { MdSettings as SettingsIcon } from 'react-icons/md';
import { logout as _logout } from '../../redux/actions/userActions';
import { useIsAuthenticated } from '../../redux/selectors/userSelectors';
import appIcon from '../../assets/appLogo64.png';
import { classnames } from '../../utils';
import { GITHUB_PUBLIC_AUTH_URL } from '../../constants';
@@ -61,8 +62,7 @@ MobileLink.defaultProps = defaultProps;
const Header = ({ mode }) => {
const [toggle, setToggle] = useState(false);
const userId = useSelector((state) => state.user.userId);
const isAuthenticated = userId && userId.length > 0;
const isAuthenticated = useIsAuthenticated();
const dispatch = useDispatch();
const logout = () => dispatch(_logout());
@@ -1,5 +1,4 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { FaGithub as GithubIcon } from 'react-icons/fa';
@@ -13,9 +12,6 @@ import { classnames } from '../../utils';
import mockup from '../../assets/mockup.png';
const SignUpScreen = () => {
// eslint-disable-next-line no-unused-vars
const userId = useSelector((state) => state.user.userId);
return (
<div className="h-full flex flex-wrap">
<div className="hidden lg:block lg:w-3/5 lg:p-8 lg:my-auto">
+9 -5
View File
@@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useDispatch } from 'react-redux';
import BounceLoader from 'react-spinners/BounceLoader';
import { v4 as uuidv4 } from 'uuid';
@@ -19,14 +19,18 @@ import { CardTypes } from '../../utils';
import { DEFAULT_OPTION as STATS_DEFAULT_RANK } from '../../components/Home/StatsRankSection';
import { DEFAULT_OPTION as LANGUAGES_DEFAULT_LAYOUT } from '../../components/Home/LanguagesLayoutSection';
import { DEFAULT_OPTION as WAKATIME_DEFAULT_LAYOUT } from '../../components/Home/WakatimeLayoutSection';
import {
useUserId,
useIsAuthenticated,
usePrivateAccess,
} from '../../redux/selectors/userSelectors';
const HomeScreen = () => {
const [isLoading, setIsLoading] = useState(false);
const userId = useSelector((state) => state.user.userId);
const privateAccess = useSelector((state) => state.user.privateAccess);
const isAuthenticated = userId && userId.length > 0;
const userId = useUserId();
const privateAccess = usePrivateAccess();
const isAuthenticated = useIsAuthenticated();
const dispatch = useDispatch();
@@ -2,7 +2,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
import { useDispatch } from 'react-redux';
import { Button, Image } from '../../../components';
import { classnames } from '../../../utils';
@@ -13,12 +13,16 @@ import {
} from '../../../constants';
import { FaGithub as GithubIcon } from 'react-icons/fa';
import { logout as _logout } from '../../../redux/actions/userActions';
import {
useIsAuthenticated,
usePrivateAccess,
useUserKey,
} from '../../../redux/selectors/userSelectors';
const LoginStage = ({ setCurrItem }) => {
const userId = useSelector((state) => state.user.userId);
const userKey = useSelector((state) => state.user.userKey);
const privateAccess = useSelector((state) => state.user.privateAccess);
const isAuthenticated = userId && userId.length > 0;
const userKey = useUserKey();
const privateAccess = usePrivateAccess();
const isAuthenticated = useIsAuthenticated();
const dispatch = useDispatch();
const logout = () => {
@@ -2,26 +2,26 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import { Card } from '../../../components';
import { useUserId } from '../../../redux/selectors/userSelectors';
const SelectCardStage = ({ selectedCard, setSelectedCard, setImageSrc }) => {
const userId = useSelector((state) => state.user.userId);
const userId = useUserId();
return (
<div className="w-full flex flex-wrap">
{[
{
title: 'GitHub Stats Card',
description: 'your overall GitHub statistics',
imageSrc: `?username=${userId || 'anuraghazra'}`,
imageSrc: `?username=${userId}`,
demoCustomization: '&include_all_commits=true',
cardType: 'stats',
},
{
title: 'Top Languages Card',
description: 'your most frequently used languages',
imageSrc: `/top-langs?username=${userId || 'anuraghazra'}`,
imageSrc: `/top-langs?username=${userId}`,
demoCustomization: '&langs_count=4',
cardType: 'top-langs',
},
@@ -1,7 +1,6 @@
/* eslint-disable react/jsx-one-expression-per-line */
import React from 'react';
import { useSelector } from 'react-redux';
import { Link } from 'react-router-dom';
import { FaCheck as CheckIcon, FaGithub as GithubIcon } from 'react-icons/fa';
@@ -13,11 +12,10 @@ import avgupta456Langs from '../../assets/avgupta456_langs.png';
import tiangoloRepos from '../../assets/tiangolo_repos.png';
import reininkRepos from '../../assets/reinink_repos.png';
import dhermesLangs from '../../assets/dhermes_langs.png';
import { useIsAuthenticated } from '../../redux/selectors/userSelectors';
function LandingScreen() {
const userId = useSelector((state) => state.user.userId);
const isAuthenticated = userId && userId.length > 0;
const isAuthenticated = useIsAuthenticated();
return (
<section>
@@ -1,9 +1,15 @@
import React, { useEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
import { useDispatch } from 'react-redux';
import { Button } from '../../components';
import { logout as _logout } from '../../redux/actions/userActions';
import {
useUserId,
useUserKey,
useIsAuthenticated,
usePrivateAccess,
} from '../../redux/selectors/userSelectors';
import { deleteAccount } from '../../api';
import { classnames } from '../../utils';
import { CLIENT_ID, GITHUB_PRIVATE_AUTH_URL, HOST } from '../../constants';
@@ -70,10 +76,10 @@ const SettingsScreen = () => {
const wrapperRef = useRef(null);
useOutsideAlerter(wrapperRef, closeDeleteModal);
const userId = useSelector((state) => state.user.userId);
const isAuthenticated = userId && userId.length > 0;
const userKey = useSelector((state) => state.user.userKey);
const privateAccess = useSelector((state) => state.user.privateAccess);
const userId = useUserId();
const userKey = useUserKey();
const isAuthenticated = useIsAuthenticated();
const privateAccess = usePrivateAccess();
const accountTier = privateAccess ? 'Private Workflow' : 'Public Workflow';
const dispatch = useDispatch();
@@ -0,0 +1,24 @@
import { useSelector } from 'react-redux';
export const useUserId = () => {
return useSelector((state) => state.user.userId) || 'anuraghazra';
};
export const useIsAuthenticated = () => {
return useSelector((state) => {
const userId = state.user.userId;
return userId && userId.length > 0;
});
};
export const usePrivateAccess = () => {
return useSelector((state) => state.user.privateAccess);
};
export const useUserKey = () => {
return useSelector((state) => state.user.userKey);
};
export const useUserToken = () => {
return useSelector((state) => state.user.token);
};