React中sessionStorage.getItem为何无法读取跨页面传递的token值?
Let's break down what's happening here and fix that token issue once and for all. The "unexpected end of JSON" error is a clue—it means your API is returning a non-JSON response (like an HTML error page for unauthorized access) because your token isn't being sent correctly. Here's how to diagnose and fix the problem:
First, Let's Diagnose the Root Conflict
You mentioned sessionStorage.token logs correctly in your render method, but sessionStorage.getItem('token') returns nothing in componentDidMount. Wait—React's lifecycle order means render runs before componentDidMount, so if render can see the token, componentDidMount should too. This inconsistency points to a few likely issues:
Inconsistent sessionStorage access patterns
You're setting the token with dot notation (sessionStorage.token = token) but retrieving it withgetItem(). While this usually works, edge cases like implicit type conversion or accidental key mismatches can break things. SessionStorage only stores strings, so let's standardize our approach.Race condition during page navigation
Even though you're navigating in the login fetch's.then()block, there's a tiny chance the Landing page starts loading before the token is fully persisted to sessionStorage. Or, your login API'sdata.tokenmight be an object instead of a string (which gets stored as"[object Object]"instead of the actual token).The JSON error is a side effect
The "unexpected end of JSON" error happens because your API returns an error page (not valid JSON) when it gets an invalid Authorization header. Fixing the token issue will automatically resolve this.
Step-by-Step Fixes to Try
1. Standardize SessionStorage Usage
First, update your Login page to use explicit setItem() instead of dot notation to store the token:
// Login page handleSubmit function .then(data => { sessionStorage.setItem('token', data.token); // Explicit storage method this.props.history.push('/landing'); })
Then in your Landing page's componentDidMount, use getItem() consistently, and add checks to catch missing tokens:
componentDidMount() { const token = sessionStorage.getItem('token'); console.log('Token in componentDidMount:', token); // Add this to confirm the value // Redirect to login if token is missing if (!token) { this.props.history.push('/login'); return; } fetch('http://myapiclient:11111/api/clients', { method: 'GET', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` // Use template strings for cleaner syntax }, }) .then(results => { // Check if the response is valid before parsing JSON if (!results.ok) { throw new Error(`Request failed: ${results.status}`); } return results.json(); }) .then(data => this.setState({ data: data })) .catch(err => console.error('Fetch error details:', err)); // Log full error info }
2. Verify Token Value at Every Step
- In your Login page, after setting the token, log
sessionStorage.getItem('token')to confirm it's the correct string (not an object orundefined). - Check your browser's Application > Session Storage tab before navigating to the Landing page—this will tell you if the token is actually being stored.
- The
console.logincomponentDidMountwill show you exactly what value is being sent to the API. If it'snull, your login logic isn't storing the token correctly.
3. Fallback: Pass Token via Route State
If sessionStorage still gives you trouble, bypass it entirely for the initial page load by passing the token directly through your route:
// Login page navigation .then(data => { this.props.history.push({ pathname: '/landing', state: { token: data.token } // Pass token as route state }); })
Then access it in your Landing page:
componentDidMount() { // Use route state first, fall back to sessionStorage const token = this.props.location.state?.token || sessionStorage.getItem('token'); if (!token) { this.props.history.push('/login'); return; } // Rest of your fetch code... }
Final Checks
- Ensure your login API returns a valid string token (not an object).
- Double-check for typos in the token key name—it's case-sensitive (
'token'vs'Token'will break things). - Confirm your API expects the exact format
Bearer <token>(with a single space between "Bearer" and the token).
内容的提问来源于stack exchange,提问作者user1724708

