#reactjs
#reactjs
Вопрос:
Когда я перемещаю ползунок диапазона после выбора видео, вся страница повторно отображается, как избежать этой проблемы? Как избежать ненужного повторного рендеринга компонента? Я использую реагирующие хуки. Я помещаю ползунок диапазона внутри элемента формы. Я использую React Dropzone для использования функции перетаскивания.Состояние setVideo передается компоненту ReactDropZone.Я не понимаю, почему это происходит
Здесь код,
import React, { useEffect, useState } from 'react';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import Form from 'react-bootstrap/Form';
import ReactDropZone from '../ReactDropZone';
import ProgressBar from 'react-bootstrap/ProgressBar';
import { fetchFile } from '@ffmpeg/ffmpeg';
const Compress = ({ ffmpeg }) => {
const [videoFile, setVideoFile] = useState();
const [rangeInputVal, setRangeInputVal] = useState(1);
const [progressVisibility, setProgressVisibility] = useState(false);
const [completedNow, setCompletedNow] = useState(0);
const [convertedVideo, setConvertedVideo] = useState();
const convertFun = async num => {
// Write the file to memory
ffmpeg.FS('writeFile', 'test.mp4', await fetchFile(videoFile));
// Run the FFMpeg command
await ffmpeg.run('-i', 'test.mp4', '-crf', `${num}`, 'out.mp4');
// Read the result
const data = ffmpeg.FS('readFile', 'out.mp4');
// Create a URL
const url = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));
setConvertedVideo(url);
};
useEffect(() => {
ffmpeg.setProgress(({ ratio }) => {
console.log('completed now is', parseFloat(ratio) * 100);
setCompletedNow(Math.round(parseFloat(ratio) * 100));
});
}, []);
const handleRangeInput = e => {
setRangeInputVal(e.target.value);
};
const handleCancelBtn = () => {
setVideoFile(null);
};
const handleSubmit = e => {
e.preventDefault();
setTimeout(() => {
setProgressVisibility(true);
}, 200);
convertFun(e.target.range.value);
console.log(e.target.range.value);
};
console.log('compress video:-', videoFile);
return (
<div className="compress">
<div className="compress__container">
<Row className="align-items-center justify-content-center">
<Col md={12} sm={12} lg={6} className="fileuploader__area">
{videoFile ? (
<figure>
<video controls src={URL.createObjectURL(videoFile)} />
<button className="cancelVideo" onClick={handleCancelBtn}>
X
</button>
</figure>
) : (
<ReactDropZone setVideoFile={setVideoFile} />
)}
</Col>
<Col md={12} sm={12} lg={6}>
<div className="compress__content">
<form onSubmit={handleSubmit}>
<Form.Group className="choose__quality">
<Form.Label>choose quality:-</Form.Label>
<br />
<Form.Control
type="range"
min="1"
max="50"
name="range"
value={rangeInputVal}
onChange={handleRangeInput}
/>
<span>{rangeInputVal amp;amp; rangeInputVal}</span>
<br />
<p>(higher the value,smaller the size)</p>
</Form.Group>
<Form.Group>
<button
disabled={videoFile ? false : true}
style={{ opacity: videoFile ? 1 : 0.5 }}
type="submit"
className="customBtn customBtn__small">
Start conversion
</button>
</Form.Group>
</form>
<Form.Group>
{progressVisibility amp;amp; (
<ProgressBar animated now={completedNow} label={`${completedNow} %`} />
)}
</Form.Group>
<Form.Group className="download__video">
{completedNow === 100 amp;amp; (
<p>
Video is successfully converted.{' '}
<a
href={convertedVideo}
className="downloadLink"
download={`${videoFile amp;amp; videoFile.name}`}>
Click here to download
</a>{' '}
</p>
)}
</Form.Group>
</div>
</Col>
</Row>
</div>
</div>
);
};
export default Compress;
Ответ №1:
Предполагается, что компонент будет повторно отображаться при изменении состояния, поэтому вызов «setRangeInputVal», например, приведет к повторному отображению компонента. Что-то, что, возможно, стоит попробовать, — это поместить код для видео в его собственный компонент и обернуть его с помощью React memo HOC.
const Video = React.memo((videoFile, handleCancelBtn) => {
return <figure>
<video controls src={URL.createObjectURL(videoFile)} />
<button className="cancelVideo" onClick={handleCancelBtn}>
X
</button>
</figure>
});
Используя memo HOC, если реквизит, переданный компоненту, не изменился с момента последнего рендеринга, React пропустит рендеринг этого компонента. Более подробную информацию об этом можно найти в документации React здесь: https://reactjs.org/docs/react-api.html#reactmemo .
Комментарии:
1. Спасибо за разъяснение моих сомнений. Являются ли React.memo и useMemo одинаковыми?
2. Теперь я получаю эту ошибку, TypeError: не удалось выполнить ‘createObjectURL’ на ‘URL’: сбой разрешения перегрузки.
3. Даже после попытки React.memo страница все еще перерисовывается