#reactjs
Вопрос:
Я создал статический веб-сайт React и разместил его на страницах Github.
Как вы можете видеть, всякий раз, когда вы нажимаете на фильм или сериал, появляется модал с постером фильма/телевизора(загруженным из API OMDb) и некоторыми метаданными. Проблема в том, что контент загружается слишком медленно. Требуется секунда(иногда больше), прежде чем появится содержимое.
Я понимаю, что не могу ожидать, что он загрузится намного быстрее, но я бы хотел вообще не показывать модал, пока все не будет выглядеть хорошо(т. Е. Идеально загружено). Возможно, благодаря появлению «Загрузка..», пока мы ждем. Это не должно быть чем-то необычным, так как оно будет отображаться на экране не более 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}amp;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;
Ответ №1:
Установите loading
значение true
перед вызовом api и установите loading
false
значение после того, как api вернет успех/сбой.
Проверьте обновленный код ниже
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}amp;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
Вместо того, чтобы извлекать данные внутри 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>
);
}