如何将API返回数据设置为React组件的初始状态?
问题原因
- 直接将组件实例存储在state中,初始化
<About user={user} />时user为初始空对象,该组件实例会作为快照保存在state内,后续接口请求完成更新user后,state中的旧组件实例不会自动同步最新的user数据。仅当点击tab重新传入最新user生成新组件实例时,数据才会正常渲染。 - 原有
About组件的加载判断逻辑失效:初始user为空对象,if(user)判断始终为真,不会触发加载态展示。
修复方案
- 替换存储组件实例的state,改为存储当前激活的tab标识,渲染时根据标识动态生成对应组件,自动绑定最新的
user数据 - 移除原生DOM操作样式的逻辑,改用React声明式语法控制激活tab的样式
- 调整
user初始值为null,保证加载态判断正常生效
完整修改后代码
import { useHistory, useState, useEffect } from 'react'; // 其他依赖引入比如FontAwesomeIcon、api、Navbar等自行保留 const Profile = () => { let history = useHistory(); // 初始user设为null,方便判断加载状态 const [user, setUser] = useState(null); // 存储当前激活的tab标识,代替原来存储组件实例的state const [activeTab, setActiveTab] = useState('About'); useEffect(() => { async function fetchMyAPI() { try { let res = await api.get('user/isLoggedIn', { withCredentials: true }); if (res.data.user) { setUser(res.data.user); } }catch (err) { history.push('/login'); } } fetchMyAPI(); }, []); const About = ({ user }) => { if (user) return ( <div className="about_wrapper"> <p className="name_about">{`${user.name}`}</p> <p className="email_about">{`${user.email}`}</p> <p><FontAwesomeIcon icon={faPen} />{` ${user.niche}`}</p> <p><FontAwesomeIcon icon={faAlignLeft} />{` ${user.job}`}</p> <p className="description_about"><FontAwesomeIcon icon={faAddressBook} />{` ${user.description}`}</p> </div> ); else return ( <h3>Loading..</h3> ); } const Blogs = ({ user }) => { return ( <> </> ); } const Stats = ({ user }) => { return ( <> </> ); } const clickHandler = (tabName) => { setActiveTab(tabName); } // 全局加载状态判断,也可以保留组件内的单独加载逻辑 if(!user) return <h3>加载中...</h3> return ( <> <Navbar /> <div> <div className="CoverImage FlexEmbed FlexEmbed--2by1" style={{ backgroundImage: `url(${user.cover})` }}></div> <img className="avatar" src={`${user.dp}`} alt="头像" /> <div className="info"> <p className={`info_links link-grow un ${activeTab === 'About' ? 'un-p' : ''}`} onClick={() => clickHandler('About')}>About</p> <p className={`info_links un ${activeTab === 'Blogs' ? 'un-p' : ''}`} onClick={() => clickHandler('Blogs')}>Blogs</p> <p className={`info_links un ${activeTab === 'Stats' ? 'un-p' : ''}`} onClick={() => clickHandler('Stats')}>Stats</p> </div> {/* 动态渲染当前选中的tab组件,自动传入最新的user */} {activeTab === 'About' && <About user={user} />} {activeTab === 'Blogs' && <Blogs user={user} />} {activeTab === 'Stats' && <Stats user={user} />} </div> </> ); } export default Profile
内容的提问来源于stack exchange,提问作者Rhythm Shandlya
相关产品推荐
相关产品推荐

