【问题标题】:React: don't show modal until all content has been properly loaded反应:在正确加载所有内容之前不显示模式
【发布时间】:2021-04-20 15:02:13
【问题描述】:

我创建了一个静态 React 网站并将其托管在 Github 页面上。

如您所见,每当您点击电影或电视剧时,都会出现一个模式,其中包含电影/电视海报(从 OMDb API 加载)和一些元数据。问题是内容加载太慢。内容出现之前需要一秒钟(有时更长时间)。

我知道我不能指望它加载得更快,但我不想在一切看起来不错(即完美加载)之前完全不显示模式。也许通过在我们等待时出现“正在加载..”。它不必花哨,因为它最多只会在屏幕上显示 1-2 秒。

您对 React 初学者有什么建议吗?

相关代码:

function ImdbInfo(props) {
    const [data, setData] = useState({ imdbData: [] });
 
    useEffect(() => {
        const imdbId = getImdbId(props.url);

        const fetchData = async () => {
            const result = await axios(
                `https://www.omdbapi.com/?i=${imdbId}&apiKey=${apiKey}`,
            );
            setData(result.data);
        };
        fetchData();
    }, []); // eslint-disable-line react-hooks/exhaustive-deps

    return (
        <div className="modal-content">
            <div className="metadata" onClick={props.handleClose}>
                <h1 className="modal-header">{data.Title}</h1>
                <img className="modal-poster" src={data.Poster} alt="poster" />
                <p className="modal-info">{getDirectorOrWriter(data)}</p>
                <p className="modal-info">IMDb Rating: {getImdbScore(data.Ratings)}</p>
            </div>
            {createImdbLink(props.url)}
        </div>
    );
}

还有:

const MediaModal = ({ handleClose, show, data }) => {
    const showHideClassName = show ? 'modal display-block' : 'modal display-none';
    const imdbData = show ? <ImdbInfo url={data.imdbLink} handleClose={handleClose} /> : <div />;
  
    return (
      <div className={showHideClassName} onClick={handleClose}>
        <section className='modal-main'>
            {imdbData}
        </section>
      </div>
    );
};

export default MediaModal;

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    在调用 api 之前将 loading 设置为 true 在api返回成功/失败后设置loadingfalse

    检查下面的更新代码

      function ImdbInfo(props) {
        const [data, setData] = useState({ imdbData: [] });
        const [loading, setLoading] = useState(false);
    
        useEffect(() => {
          const imdbId = getImdbId(props.url);
    
          const fetchData = async () => {
            setLoading(true);
            try {
              const result = await axios(
                `https://www.omdbapi.com/?i=${imdbId}&apiKey=${apiKey}`
              );
              setData(result.data);
              setLoading(false);
            } catch (err) {
              setLoading(false);
            }
          };
          fetchData();
        }, []); // eslint-disable-line react-hooks/exhaustive-deps
    
        return (
          <div>
            {loading ? (
              <div>Loading...</div>
            ) : (
              <div className="modal-content">
                <div className="metadata" onClick={props.handleClose}>
                  <h1 className="modal-header">{data.Title}</h1>
                  <img className="modal-poster" src={data.Poster} alt="poster" />
                  <p className="modal-info">{getDirectorOrWriter(data)}</p>
                  <p className="modal-info">
                    IMDb Rating: {getImdbScore(data.Ratings)}
                  </p>
                </div>
                {createImdbLink(props.url)}
              </div>
            )}
          </div>
        );
      }
    

    【讨论】:

      【解决方案2】:

      如果我正确理解您的代码,您将创建一个 MediaModal 组件,该组件有一个子组件 ImdbInfo,您可以在其中获取一些数据。我猜这个MediaModal 有一个父组件,您可以在其中切换和使用您的模式:您没有提供代码,但我们称之为MainComponent

      您可以在MainComponent 中获取它们并将结果作为道具传递,而不是在ImdbInfo 中获取数据:

      • MainComponent 内部:
      // Onclick to toggle modal:
      // - fetch data just like you did in ImdbInfo
      // - then set show=true
      // Then use your modal
      <MediaModal handleClose={plop} show={plip} infos={fetchedData} url={imdbLink} />
      
      • 媒体模式:
      const MediaModal = ({ handleClose, show, infos, url}) => {
          const showHideClassName = show ? 'modal display-block' : 'modal display-none';
          const imdbData = show ? <ImdbInfo infos={infos} url={url} handleClose={handleClose} /> : <div />;
        
          return (
            <div className={showHideClassName} onClick={handleClose}>
              <section className='modal-main'>
                  {imdbData}
              </section>
            </div>
          );
      };
      
      export default MediaModal;
      
      • ImdbInfo:
      function ImdbInfo({infos, handleClose}) {
          return (
              <div className="modal-content">
                  <div className="metadata" onClick={handleClose}>
                      <h1 className="modal-header">{infos.Title}</h1>
                      <img className="modal-poster" src={infos.Poster} alt="poster" />
                      <p className="modal-info">{getDirectorOrWriter(infos)}</p>
                      <p className="modal-info">IMDb Rating: {getImdbScore(infos.Ratings)}</p>
                  </div>
                  {createImdbLink(url)}
              </div>
          );
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-27
        • 1970-01-01
        • 2018-09-25
        • 2013-04-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多