React函数组件首次挂载报错:Cannot read properties of null (reading 'rooms')
React异步State更新导致的首次渲染报错问题解决
问题原因
你遇到的报错核心原因是React的setState(包括函数组件的setRoomDetails)是异步操作:
- 调用
setRoomDetails(data)后,roomDetails并不会立即更新为接口返回的data,此时它仍然是初始值null,所以第12行尝试访问roomDetails.rooms就会触发Cannot read properties of null的错误。 - 第13行直接用接口返回的
data,所以能正常读取;热重载后组件重新渲染,roomDetails已经被赋值,此时再执行代码就不会报错。
解决方案
针对这个问题,有两种常见的解决方式:
方式一:直接使用接口返回的data(推荐)
如果只是需要在获取数据后立刻操作数据,直接用接口返回的data即可,不需要依赖还没更新的state:
const showRoomDetails = () => { callAPI(`data/meetingRoom.json`) .then((data) => { setRoomDetails(data) // 直接用data,不用roomDetails console.log("Accessing roomDetails data=>" + data.rooms[0].timeSlots.startTime[1]); console.log("Results is: " + data.rooms[0].timeSlots.startTime[0]); }) }
方式二:用useEffect监听state变化
如果需要在roomDetails更新完成后执行逻辑(比如渲染数据、做后续处理),可以新增一个useEffect监听roomDetails的变化:
function HomePage() { const [roomDetails, setRoomDetails] = useState(null) const showRoomDetails = () => { callAPI(`data/meetingRoom.json`) .then((data) => { setRoomDetails(data) console.log("Results is: " + data.rooms[0].timeSlots.startTime[0]); }) } useEffect(() => { showRoomDetails() }, []) // 监听roomDetails变化,更新后执行操作 useEffect(() => { if (roomDetails) { // 先判断是否有值,避免初始null的情况 console.log("Accessing roomDetails data after update=>" + roomDetails.rooms[0].timeSlots.startTime[1]); } }, [roomDetails]) // 依赖roomDetails,当它变化时触发 return ( <> <h1 className='text-4xl'>Welcome to online room booking system</h1> </> ) }
额外优化:给state设置初始默认值
可以把state的初始值从null改成空对象{},再配合可选链操作符?.避免报错,让代码更健壮:
const [roomDetails, setRoomDetails] = useState({}) // 后续访问时用可选链 console.log(roomDetails.rooms?.[0]?.timeSlots?.startTime[1]);
内容的提问来源于stack exchange,提问作者Parth Kadam
相关产品推荐
相关产品推荐

