如何将 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 组件的初始状态!

几个问题:

  1. 您正在为 user 状态提供一个真实的初始值,因此条件渲染可能没有像您预期的那样工作。 IE。由于 user 是 ({}),因此 if (user) 检查为真,您尝试呈现未定义的属性。
  2. 您正在将 JSX 存储在组件状态中,这是 React 中的一种反模式。
  3. 您在函数组件的主体中声明 React 组件,这将产生在每个渲染周期创建 new 组件的效果并卸载并重新安装组件。这会对性能产生不利影响。

AboutBlogsStats 移出 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>
    </>
  );
}