[英]State JSX component not updating
我有一個使用文件選擇器的音頻組件,在它的onChange
事件中,更新了 state 並重新加載了音頻組件。
fileLoaded = (event) => {
const url = URL.createObjectURL(event.target.files[0]);
let react_player = (
<AudioPlayer url={url} name={event.target.files[0].name} />
);
this.setState({ reactPlayer: react_player });
event.preventDefault();
};
render() {
return (
<div>
<form onSubmit={this.submitAudioFile}>
<Button
className="Button"
size="large"
variant="contained"
component="label"
startIcon={<CloudUploadIcon />}
>
Upload File
<input
accept="audio/*"
type="file"
onChange={this.fileLoaded}
style={{ display: "none" }}
/>
</Button>
</form>
{this.state.reactPlayer}
</div>
);
}
因此,每次更改文件時,都應該從 state 重新渲染reactPlayer
組件。 但這並沒有發生,即使在觸發onChange
事件后,加載到reactPlayer
中的文件也保持不變。
這是AudioPlayer
組件。
constructor(props) {
super();
this.audioRef = React.createRef();
}
componentDidMount() {
this.setState({ audioSource: this.props.url, name: this.props.name });
console.log(this.props.name);
}
state = {
playing: false,
source: null,
currentTime: 0,
totalTime: 0,
audioSource: "",
name: "",
};
playOrPauseButton = () => {
// console.log("CALLED");
// const styleJson = { color: "#000", fontSize: "50" };
if (!this.state.playing) {
return (
<PlayCircleFilledIcon
// style={styleJson}
className="playPauseButtonHover"
onClick={this.playOrPause}
/>
);
} else {
return (
<PauseCircleFilledIcon
className="playPauseButtonHover"
// style={styleJson}
onClick={this.playOrPause}
/>
);
}
};
playOrPause = () => {
// console.log("Hello");
if (this.state.playing) {
this.audioRef.current.pause();
console.log("pause");
} else {
this.audioRef.current.play();
console.log("play");
}
const prevPlayingState = this.state.playing;
this.setState({ playing: !prevPlayingState });
};
audioIsPlaying = (e) => {
this.setState({ currentTime: Math.floor(e.target.currentTime) });
this.setState({ duration: Math.floor(e.target.duration) });
// console.log(this.state.currentTime + ":" + this.state.duration);
};
audioEnded = (e) => {
console.log("ended");
this.setState({ playing: false, currentTime: 0 });
};
audioWasLoaded = (e) => {
this.setState({ duration: Math.floor(e.target.duration) });
// let x = e.target.src;
};
render() {
let x = this.playOrPauseButton();
// this.getAudioLength();
return (
<div>
<LinearProgress
className="top"
variant="determinate"
value={(this.state.currentTime * 100) / this.state.duration}
/>
<div className={styles.audioPlayerDiv}>
{x}
<div>
<p style={{ textAlign: "center" }}>
{this.state.currentTime}/{this.state.duration}
</p>
<p style={{ fontWeight: "bold" }}>{this.state.name}</p>
</div>
<audio
onLoadedMetadata={(event) => this.audioWasLoaded(event)}
onEnded={(event) => this.audioEnded(event)}
onTimeUpdate={(event) => this.audioIsPlaying(event)}
src={this.state.audioSource}
ref={this.audioRef}
/>
<NoteAddIcon className="playPauseButtonHover"></NoteAddIcon>
{/* <button style={{ alignItems: "left" }}>take note</button> */}
</div>
</div>
);
}
}
export default AudioPlayer;```
只需將 url 的名稱存儲在 state 中並渲染 jsx。
像這樣
...
state = {
url: '',
name: ''
}
fileLoaded = (event) => {
const url = URL.createObjectURL(event.target.files[0]);
let react_player = {
url,
name: event.target.files[0].name
};
this.setState({ reactPlayer: react_player });
event.preventDefault();
};
render() {
return (
<div>
<form onSubmit={this.submitAudioFile}>
<Button
className="Button"
size="large"
variant="contained"
component="label"
startIcon={<CloudUploadIcon />}
>
Upload File
<input
accept="audio/*"
type="file"
onChange={this.fileLoaded}
style={{ display: "none" }}
/>
</Button>
</form>
{/* {this.state.reactPlayer} */}
{this.state.url && <AudioPlayer url={this.state.url} name={this.state.name} />}
</div>
);
}
找到了解決方案。 訣竅是傳遞道具並篡改AudioPlayer
組件中的 state。
<audio
onLoadedMetadata={(event) => this.audioWasLoaded(event)}
onEnded={(event) => this.audioEnded(event)}
onTimeUpdate={(event) => this.audioIsPlaying(event)}
src={this.props.url}
ref={this.audioRef}
/>
只需將音頻標簽的 src 連接到從父組件傳遞的道具,一切都很好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.