Reputation: 124
I am making the profile page for my website, but when I initially render components the data from the API somehow doesn't load up in the initial 'state' I made for About, Blog or Stats.
However when I click on About again the the API data is rendered.
IDK if I am able to make my point, but this is how my react functional component looks like:
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>
</>
);
}
export default Profile
I want to set the data from my API as initial state for my react component!
Upvotes: 2
Views: 2478
Reputation: 202667
Few issues:
user
state so the conditional rendering isn't working as you are probably expecting. I.E. since user
is ({}
) the if (user)
check is true and you attempt to render the undefined properties.Move About
, Blogs
, and Stats
out of Profile
component so they have stable references.
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 (
<>
</>
);
};
Store the component "type" in state and conditionally render them, passing the user
state to them.
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>
</>
);
}
Upvotes: 1