{"library":"react-token-auth","title":"React Token Auth","description":"The `react-token-auth` library, currently at version 2.3.8, offers a specialized solution for managing JWT `accessToken` and `refreshToken` pairs within React applications. Its primary function is to abstract the complexities of token storage (e.g., `localStorage` for web or custom async storage for React Native), synchronize the application's authentication state, and automatically handle token expiration and refreshing. A key feature is its `onUpdateToken` callback, which allows developers to integrate with their backend's token refresh endpoint, and its mechanism to prevent concurrent token update requests. While the author acknowledges that cookie-based sessions are generally preferred for web security, `react-token-auth` addresses specific use cases where client-side JWT storage is a requirement. The library provides a concise API including `createAuthProvider` to configure the system, `useAuth` to access the authentication state in components, and `authFetch` to automatically attach tokens to requests. The project appears actively maintained with regular updates and ships with TypeScript type definitions, making it suitable for modern React development practices.","language":"javascript","status":"active","last_verified":"Wed Apr 22","install":{"commands":["npm install react-token-auth"],"cli":null},"imports":["import { createAuthProvider } from 'react-token-auth';","import { useAuth } from 'react-token-auth';","import { login } from 'react-token-auth';"],"auth":{"required":false,"env_vars":[]},"quickstart":{"code":"import { createAuthProvider } from 'react-token-auth';\nimport React, { FormEvent, useEffect } from 'react';\nimport { BrowserRouter, Switch, Route, Redirect } from 'react-router-dom'; // Assuming react-router-dom for routing context\n\n// Define the shape of your session object\ntype Session = { accessToken: string; refreshToken: string };\n\n// 1. Create the auth provider instance\nexport const { useAuth, authFetch, login, logout } = createAuthProvider<Session>({\n    getAccessToken: session => session.accessToken,\n    // Use localStorage for web applications. Ensure it's available (e.g., client-side).\n    storage: typeof window !== 'undefined' ? localStorage : undefined,\n    onUpdateToken: async (token: { refreshToken: string }) => {\n        // This function is called when the accessToken needs to be refreshed.\n        // It must return a new session object { accessToken: string; refreshToken: string }\n        try {\n            const response = await fetch('/update-token', {\n                method: 'POST',\n                headers: { 'Content-Type': 'application/json' },\n                body: JSON.stringify({ refreshToken: token.refreshToken }),\n            });\n            if (!response.ok) {\n                const errorData = await response.json();\n                console.error('Token refresh failed:', errorData);\n                throw new Error('Failed to refresh token');\n            }\n            return response.json();\n        } catch (error) {\n            console.error('Network or server error during token refresh:', error);\n            throw error;\n        }\n    },\n    // Optional: Callback when a session is loaded from storage (hydration)\n    onHydratation: session => {\n        console.log('Session hydrated:', session);\n    },\n});\n\n// A dummy component for registration\nconst Register = () => <div>Register Page</div>;\n\n// 2. Example Login Component\nconst Login = () => {\n    const onSubmit = async (e: FormEvent) => {\n        e.preventDefault();\n        // Simulate a login API call\n        try {\n            const response = await fetch('/login', {\n                method: 'POST',\n                headers: { 'Content-Type': 'application/json' },\n                body: JSON.stringify({ username: 'testuser', password: 'password' }), // Replace with actual credentials\n            });\n            if (!response.ok) {\n                const errorData = await response.json();\n                console.error('Login failed:', errorData);\n                alert('Login failed!');\n                return;\n            }\n            const session = await response.json();\n            login(session); // Save the new session\n            alert('Logged in successfully!');\n        } catch (error) {\n            console.error('Network error during login:', error);\n            alert('Network error during login!');\n        }\n    };\n\n    return (\n        <form onSubmit={onSubmit}>\n            <h2>Login</h2>\n            <input type=\"text\" placeholder=\"Username\" />\n            <input type=\"password\" placeholder=\"Password\" />\n            <button type=\"submit\">Login</button>\n        </form>\n    );\n};\n\n// A dummy dashboard component\nconst Dashboard = () => {\n    const handleLogout = () => {\n        logout();\n        alert('Logged out!');\n    };\n\n    // Example of using authFetch to make authenticated requests\n    const fetchData = async () => {\n        try {\n            const response = await authFetch('/api/protected-data');\n            const data = await response.json();\n            console.log('Protected data:', data);\n            alert('Fetched protected data: ' + JSON.stringify(data));\n        } catch (error) {\n            console.error('Failed to fetch protected data:', error);\n            alert('Failed to fetch protected data. Maybe token expired or invalid.');\n        }\n    };\n\n    return (\n        <div>\n            <h2>Dashboard</h2>\n            <button onClick={handleLogout}>Logout</button>\n            <button onClick={fetchData}>Fetch Protected Data</button>\n        </div>\n    );\n};\n\n// 3. Main Router component using useAuth hook to manage routing based on auth state\nconst AppRouter = () => {\n    const [logged, session] = useAuth(); // Get current auth state\n\n    useEffect(() => {\n        console.log('Auth state changed:', logged, session);\n    }, [logged, session]);\n\n    return (\n        <BrowserRouter>\n            <Switch>\n                {!logged ? (\n                    <>\n                        <Route path=\"/register\" component={Register} />\n                        <Route path=\"/login\" component={Login} />\n                        <Redirect to=\"/login\" />\n                    </>\n                ) : (\n                    <>\n                        <Route path=\"/dashboard\" component={Dashboard} exact />\n                        <Redirect to=\"/dashboard\" />\n                    </>\n                )}\n            </Switch>\n        </BrowserRouter>\n    );\n};\n\n// To run this example in a real React app, you would render <AppRouter /> in your ReactDOM.render()\n// For demonstration purposes, we omit the ReactDOM.render() call.","lang":"typescript","description":"This quickstart demonstrates the core functionality: initializing the auth provider, implementing login/logout, using the `useAuth` hook for conditional rendering, and making authenticated API calls with `authFetch`.","tag":null,"tag_description":null,"last_tested":null,"results":[]},"compatibility":null}