React中useState初始值为null时访问user.username引发TypeError的原因解析
Let's break down exactly what caused the error and why your two fixes resolved it:
The Root Cause: Initial Render vs. Async Data Loading
Your original code initializes user as null with const [user,setUser] = useState(null);. Here's the sequence of events that leads to the TypeError:
- When the component first renders, React uses the initial state value (
null) to render the UI. - At this point, your JSX tries to access
user.username— which is equivalent to trying to accessnull.username. Sincenullis a primitive value with no properties or prototype chain, this immediately throws aTypeError: Cannot read properties of null (reading 'username'). - The
useEffecthook runs after the initial render, sends the axios request, and eventually updatesuserwith the fetched data. But by then, the initial render has already failed with the error.
The tutorial might have avoided this issue by either:
- Adding a loading state (e.g., checking if
userisnulland rendering a placeholder instead) - Initializing
userwith an empty object ({}) instead ofnull(since accessing{}.usernamereturnsundefinedwithout throwing an error) - Using optional chaining (more on that below)
Why Your Fixes Worked
Fix 1: Initializing user as an empty string ('')
When you set const [user,setUser] = useState('');, the initial render tries to access ''.username. Unlike null, strings are objects in JavaScript (they have a prototype chain), so accessing a non-existent property on them returns undefined instead of throwing an error. The UI will render an empty value until the axios request completes and updates user with the fetched user object.
Fix 2: Storing just the username in state
By changing setUser(res.data) to setUser(res.data.username) and rendering {user} directly:
- Now
userholds a string (the username) once the request completes. - On initial render,
useris stillnull, but rendering{user}will just displaynull(or nothing, depending on how your CSS handles it) instead of trying to access a property onnull, so no error is thrown.
Better Practices to Avoid This Issue
Instead of relying on workarounds, here are more robust approaches:
- Use optional chaining: Update your JSX to
{user?.username}. The?.operator safely accesses theusernameproperty only ifuseris notnullorundefined. - Add a loading state: Render a placeholder (like a spinner) while waiting for the data:
if (!user) return <div className='conversation'>Loading...</div>; return( <div className='conversation'> <img className='conversationImg' src='https://img.seoul.co.kr/img/upload/2020/05/25/SSI_20200525111945_O2.jpg' alt='' /> <span className='conversationName'>{user.username}</span> </div> ); - Initialize with an empty object: Set
const [user,setUser] = useState({});. This way,user.usernamewill beundefinedon initial render (no error) and update to the actual username once the request finishes.
内容的提问来源于stack exchange,提问作者thebat

