如何将 API 中的数据设置为我的 React 组件的初始状态?
How to set the data from my API as initial state for my react component?
我正在为我的网站制作个人资料页面,但是当我最初呈现组件时,来自 API 的数据不知何故不会加载到最初的 'state' 我为关于,博客制作或统计数据。
但是,当我再次单击“关于”时,会呈现 API 数据。
IDK 如果我能表达我的观点,但这是我的反应功能组件的样子:
const Profile = () => {
let history = useHistory();
const [user, setUser] = useState({});
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 = (props) => {
return (
<>
</>
);
}
const Stats = (props) => {
return (
<>
</>
);
}
const [state, stateSetter] = useState(<About user={user}/>);
const clickHandler = (e) => {
e.preventDefault()
const nav = document.querySelectorAll('.info_links');
switch (e.target.textContent) {
case 'About':
nav[1].classList.remove('un-p');
nav[2].classList.remove('un-p');
stateSetter(<About user={user}/>);
break;
case 'Stats':
nav[0].classList.remove('un-p');
nav[1].classList.remove('un-p');
stateSetter(<Stats user={user}/>);
break;
case 'Blogs':
nav[0].classList.remove('un-p');
nav[2].classList.remove('un-p');
stateSetter(<Blogs user={user}/>);
break;
default:
console.log('error')
}
e.target.classList.add('un-p');
}
return (
<>
<Navbar />
<div>
<div className="CoverImage FlexEmbed FlexEmbed--2by1" style={{ backgroundImage: `url(${user.cover}})` }}></div>
<img className="avatar" src={`${user.dp}`} alt="Girl in a jacket" />
<div className="info">
<p className="info_links link-grow un un-p" onClick={clickHandler}>About</p>
<p className="info_links un" onClick={clickHandler}>Blogs</p>
<p className="info_links un" onClick={clickHandler}>Stats</p>
</div>
{state}
</div>
</>
);
}
导出默认配置文件
我想将 API 中的数据设置为我的 React 组件的初始状态!
几个问题:
- 您正在为
user
状态提供一个真实的初始值,因此条件渲染可能没有像您预期的那样工作。 IE。由于 user
是 ({}
),因此 if (user)
检查为真,您尝试呈现未定义的属性。
- 您正在将 JSX 存储在组件状态中,这是 React 中的一种反模式。
- 您在函数组件的主体中声明 React 组件,这将产生在每个渲染周期创建 new 组件的效果并卸载并重新安装组件。这会对性能产生不利影响。
将 About
、Blogs
和 Stats
移出 Profile
组件,以便它们具有稳定的引用。
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 = (props) => {
return (
<>
</>
);
};
const Stats = (props) => {
return (
<>
</>
);
};
将组件“类型”存储在状态中并有条件地渲染它们,将 user
状态传递给它们。
const Profile = () => {
const history = useHistory();
const [user, setUser] = useState(); // <-- undefined, falsey
const [state, stateSetter] = useState('About'); // <-- use type
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 clickHandler = (e) => {
e.preventDefault()
const nav = document.querySelectorAll('.info_links');
switch (e.target.textContent) {
case 'About':
nav[1].classList.remove('un-p');
nav[2].classList.remove('un-p');
stateSetter('About'); // <-- update state type
break;
case 'Stats':
nav[0].classList.remove('un-p');
nav[1].classList.remove('un-p');
stateSetter('Stats'); // <-- update state type
break;
case 'Blogs':
nav[0].classList.remove('un-p');
nav[2].classList.remove('un-p');
stateSetter('Blogs'); // <-- update state type
break;
default:
console.log('error')
}
e.target.classList.add('un-p');
}
return (
<>
<Navbar />
<div>
<div
className="CoverImage FlexEmbed FlexEmbed--2by1"
style={{ backgroundImage: `url(${user.cover}})` }}>
</div>
<img className="avatar" src={`${user.dp}`} alt="Girl in a jacket" />
<div className="info">
<p className="info_links link-grow un un-p" onClick={clickHandler}>About</p>
<p className="info_links un" onClick={clickHandler}>Blogs</p>
<p className="info_links un" onClick={clickHandler}>Stats</p>
</div>
{state === 'About' && <About user={user} />}
{state === 'Stats' && <Stats user={user} />}
{state === 'Blogs' && <Blogs user={user} />}
</div>
</>
);
}
我正在为我的网站制作个人资料页面,但是当我最初呈现组件时,来自 API 的数据不知何故不会加载到最初的 'state' 我为关于,博客制作或统计数据。
但是,当我再次单击“关于”时,会呈现 API 数据。
IDK 如果我能表达我的观点,但这是我的反应功能组件的样子:
const Profile = () => {
let history = useHistory();
const [user, setUser] = useState({});
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 = (props) => {
return (
<>
</>
);
}
const Stats = (props) => {
return (
<>
</>
);
}
const [state, stateSetter] = useState(<About user={user}/>);
const clickHandler = (e) => {
e.preventDefault()
const nav = document.querySelectorAll('.info_links');
switch (e.target.textContent) {
case 'About':
nav[1].classList.remove('un-p');
nav[2].classList.remove('un-p');
stateSetter(<About user={user}/>);
break;
case 'Stats':
nav[0].classList.remove('un-p');
nav[1].classList.remove('un-p');
stateSetter(<Stats user={user}/>);
break;
case 'Blogs':
nav[0].classList.remove('un-p');
nav[2].classList.remove('un-p');
stateSetter(<Blogs user={user}/>);
break;
default:
console.log('error')
}
e.target.classList.add('un-p');
}
return (
<>
<Navbar />
<div>
<div className="CoverImage FlexEmbed FlexEmbed--2by1" style={{ backgroundImage: `url(${user.cover}})` }}></div>
<img className="avatar" src={`${user.dp}`} alt="Girl in a jacket" />
<div className="info">
<p className="info_links link-grow un un-p" onClick={clickHandler}>About</p>
<p className="info_links un" onClick={clickHandler}>Blogs</p>
<p className="info_links un" onClick={clickHandler}>Stats</p>
</div>
{state}
</div>
</>
);
}
导出默认配置文件
我想将 API 中的数据设置为我的 React 组件的初始状态!
几个问题:
- 您正在为
user
状态提供一个真实的初始值,因此条件渲染可能没有像您预期的那样工作。 IE。由于user
是 ({}
),因此if (user)
检查为真,您尝试呈现未定义的属性。 - 您正在将 JSX 存储在组件状态中,这是 React 中的一种反模式。
- 您在函数组件的主体中声明 React 组件,这将产生在每个渲染周期创建 new 组件的效果并卸载并重新安装组件。这会对性能产生不利影响。
将 About
、Blogs
和 Stats
移出 Profile
组件,以便它们具有稳定的引用。
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 = (props) => {
return (
<>
</>
);
};
const Stats = (props) => {
return (
<>
</>
);
};
将组件“类型”存储在状态中并有条件地渲染它们,将 user
状态传递给它们。
const Profile = () => {
const history = useHistory();
const [user, setUser] = useState(); // <-- undefined, falsey
const [state, stateSetter] = useState('About'); // <-- use type
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 clickHandler = (e) => {
e.preventDefault()
const nav = document.querySelectorAll('.info_links');
switch (e.target.textContent) {
case 'About':
nav[1].classList.remove('un-p');
nav[2].classList.remove('un-p');
stateSetter('About'); // <-- update state type
break;
case 'Stats':
nav[0].classList.remove('un-p');
nav[1].classList.remove('un-p');
stateSetter('Stats'); // <-- update state type
break;
case 'Blogs':
nav[0].classList.remove('un-p');
nav[2].classList.remove('un-p');
stateSetter('Blogs'); // <-- update state type
break;
default:
console.log('error')
}
e.target.classList.add('un-p');
}
return (
<>
<Navbar />
<div>
<div
className="CoverImage FlexEmbed FlexEmbed--2by1"
style={{ backgroundImage: `url(${user.cover}})` }}>
</div>
<img className="avatar" src={`${user.dp}`} alt="Girl in a jacket" />
<div className="info">
<p className="info_links link-grow un un-p" onClick={clickHandler}>About</p>
<p className="info_links un" onClick={clickHandler}>Blogs</p>
<p className="info_links un" onClick={clickHandler}>Stats</p>
</div>
{state === 'About' && <About user={user} />}
{state === 'Stats' && <Stats user={user} />}
{state === 'Blogs' && <Blogs user={user} />}
</div>
</>
);
}