React中API调用后设置document title出现TypeError的问题求助
问题根源与解决方案
你遇到的问题核心在于React的setState是异步操作——调用setBlogPost后,组件状态并不会立刻更新,所以你紧接着去访问blogPost.title.rendered时,blogPost还是初始的空对象{},自然会抛出Cannot read properties of undefined (reading 'rendered')的错误。
为什么你的两种尝试都失败了?
- 第一种写法的
then链:
最后一个then回调里,setBlogPost(post[0])刚刚触发,但状态还没完成更新,此时blogPost仍然是初始的空对象,根本没有title属性。 - 第二种
async/await写法:
同样的道理,setBlogPost(post[0])是异步的,调用后立刻访问blogPost,拿到的还是更新前的旧值。
两种可行的修复方案
方案1:直接使用API返回的原始数据设置标题
既然你已经在fetch的回调里拿到了完整的post[0]数据,完全不需要等到React状态更新,直接用这个数据来设置标题即可:
const getPost = async () => { try { const response = await fetch(blogPostURL); if (!response.ok) throw new Error('请求失败'); const post = await response.json(); // 先检查post[0]是否存在,避免API返回空数组的情况 if (post[0]) { document.title = post[0].title.rendered; setBlogPost(post[0]); } } catch (err) { console.error('获取文章失败:', err); } finally { setLoading(false); } }
或者用Promise链式写法:
const getPost = () => { fetch(blogPostURL) .then(response => { if (!response.ok) throw new Error('请求失败'); return response.json(); }) .then(post => { if (post[0]) { document.title = post[0].title.rendered; setBlogPost(post[0]); } setLoading(false); }) .catch(err => { console.error('获取文章失败:', err); setLoading(false); }) }
方案2:用useEffect监听blogPost状态变化
如果你必须依赖React状态来设置标题,可以新增一个useEffect,监听blogPost的变化,当状态更新完成后再修改标题:
const BlogPost = () => { const [loading, setLoading] = useState(true); const [blogPost, setBlogPost] = useState({}); let blogPostURL = dgAPI.getPostFromSlug + useParams().slug; const getPost = async () => { try { const response = await fetch(blogPostURL); if (!response.ok) throw new Error('请求失败'); const post = await response.json(); setBlogPost(post[0] || {}); // 确保即使post[0]不存在,状态也是对象 } catch (err) { console.error('获取文章失败:', err); } finally { setLoading(false); } } useEffect(() => { getPost(); }, []); // 监听blogPost变化,更新标题 useEffect(() => { // 可选链操作符避免访问不存在的属性报错 if (blogPost.title?.rendered) { document.title = blogPost.title.rendered; } }, [blogPost]); // 依赖项设为blogPost,状态变化时触发 return ( <> ... </> ) }
内容的提问来源于stack exchange,提问作者Dave Gulati
相关产品推荐
相关产品推荐

