React 条件渲染在一个地方工作,但在同一组件中不能在另一个地方工作
React conditional rendering working in one place, but not another in the same component
我正在 React 中构建一个自定义音频播放器组件,我基于 this guide 和我自己的一些 modifications/additions。我遇到的问题是应该在常规音量图标和划掉的音量图标之间切换的 muteToggle 按钮没有更新。从功能上讲它可以工作,但在单击时似乎无法呈现相应的图标。
我对我应该做什么感到困惑,因为据我所知,我使用 play/pause 按钮的过程与 完全相同单击时更新。
我应该提一下,这个组件是用 GatsbyJS 构建的静态站点的一部分。
这是代码(其他一切都按预期工作):
import React from 'react'
import {MdPlayCircleOutline, MdPauseCircleOutline, MdVolumeOff, MdVolumeUp} from "react-icons/lib/md"
import '../styles/audioplayer.css'
export default class AudioPlayer extends React.Component {
constructor(props) {
super(props);
this.state = {
play: false,
lastVolume: this.volume5,
isMute: false
};
}
componentDidMount() {
this.audio.addEventListener("timeupdate", () => {
let ratio = this.audio.currentTime / this.audio.duration;
let position = (this.timeline.offsetWidth * ratio) + this.timeline.offsetLeft;
this.positionHandle(position);
});
}
positionHandle = (position) => {
let timelineWidth = this.timeline.offsetWidth - this.handle.offsetWidth;
let handleLeft = position - this.timeline.offsetLeft;
if (handleLeft >= 0 && handleLeft <= timelineWidth) {
this.handle.style.marginLeft = handleLeft + "px";
this.played.style.width = handleLeft + "px";
}
if (handleLeft < 0) {
this.handle.style.marginLeft = "0px";
this.played.style.width = "0px";
}
if (handleLeft > timelineWidth) {
this.handle.style.marginLeft = timelineWidth + "px";
this.played.style.width = timelineWidth + "px";
}
}
mouseMove = (e) => {
this.positionHandle(e.pageX);
this.audio.currentTime = ((e.pageX - this.timeline.offsetLeft) / this.timeline.offsetWidth) * this.audio.duration;
}
mouseUp = (e) => {
window.removeEventListener('mousemove', this.mouseMove);
window.removeEventListener('mouseup', this.mouseUp);
}
mouseDown = (e) => {
window.addEventListener('mousemove', this.mouseMove);
window.addEventListener('mouseup', this.mouseUp);
}
play = () => {
if (this.state.play) {
this.setState({ play: false });
this.audio.pause();
} else {
this.setState({ play: true });
this.audio.play();
}
}
mute = () => {
if (!this.state.isMute) {
this.audio.volume = 0;
this.setState({ isMute: true });
this.volBlock1.style.background = "#a4a4a4";
this.volBlock2.style.background = "#a4a4a4";
this.volBlock3.style.background = "#a4a4a4";
this.volBlock4.style.background = "#a4a4a4";
this.volBlock5.style.background = "#a4a4a4";
console.log("isMute: ", this.state.isMute);
} else {
this.setState({ isMute: false });
this.state.lastVolume();
console.log("isMute: ", this.state.isMute);
}
}
volume1 = () => {
this.audio.volume = 0.2;
this.setState({ lastVolume: this.volume1 });
this.volBlock1.style.background = "#000000";
this.volBlock2.style.background = "#a4a4a4";
this.volBlock3.style.background = "#a4a4a4";
this.volBlock4.style.background = "#a4a4a4";
this.volBlock5.style.background = "#a4a4a4";
}
volume2 = () => {
this.audio.volume = 0.4;
this.setState({ lastVolume: this.volume2 });
this.volBlock1.style.background = "#000000";
this.volBlock2.style.background = "#000000";
this.volBlock3.style.background = "#a4a4a4";
this.volBlock4.style.background = "#a4a4a4";
this.volBlock5.style.background = "#a4a4a4";
}
volume3 = () => {
this.audio.volume = 0.6;
this.setState({ lastVolume: this.volume3 });
this.volBlock1.style.background = "#000000";
this.volBlock2.style.background = "#000000";
this.volBlock3.style.background = "#000000";
this.volBlock4.style.background = "#a4a4a4";
this.volBlock5.style.background = "#a4a4a4";
}
volume4 = () => {
this.audio.volume = 0.8;
this.setState({ lastVolume: this.volume4 });
this.volBlock1.style.background = "#000000";
this.volBlock2.style.background = "#000000";
this.volBlock3.style.background = "#000000";
this.volBlock4.style.background = "#000000";
this.volBlock5.style.background = "#a4a4a4";
}
volume5 = () => {
this.audio.volume = 1;
this.setState({ lastVolume: this.volume5 });
this.volBlock1.style.background = "#000000";
this.volBlock2.style.background = "#000000";
this.volBlock3.style.background = "#000000";
this.volBlock4.style.background = "#000000";
this.volBlock5.style.background = "#000000";
}
render() {
let playButton = null;
if (!this.state.play) {
playButton = <MdPlayCircleOutline className="pButton" onClick={this.play} />
} else {
playButton= <MdPauseCircleOutline className="pButton" onClick={this.play} />
}
let muteToggle = null;
if(!this.state.isMuted) {
muteToggle = <MdVolumeUp onClick={this.mute} />;
} else {
muteToggle = <MdVolumeOff onClick={this.mute} />;
}
return(
<div id="audioplayer">
<audio id="music" ref={(audio) => { this.audio = audio } } controls>
<source src={this.props.audio} />
</audio>
{playButton}
<div id="timeline" onClick={this.mouseMove} ref={(timeline) => { this.timeline = timeline }}>
<div id="played" ref={(played) => {this.played = played}} />
<div id="handle" onMouseDown={this.mouseDown} ref={(handle) => { this.handle = handle }} />
</div>
<div className="volume-container">
{muteToggle}
<div className="volume-item" onClick={this.volume1} >
<div className="volume-block" ref={(volBlock1) => {this.volBlock1 = volBlock1}} />
</div>
<div className="volume-item" onClick={this.volume2} >
<div className="volume-block" ref={(volBlock2) => {this.volBlock2 = volBlock2}} />
</div>
<div className="volume-item" onClick={this.volume3} >
<div className="volume-block" ref={(volBlock3) => {this.volBlock3 = volBlock3}} />
</div>
<div className="volume-item" onClick={this.volume4} >
<div className="volume-block" ref={(volBlock4) => {this.volBlock4 = volBlock4}} />
</div>
<div className="volume-item" onClick={this.volume5} >
<div className="volume-block" ref={(volBlock5) => {this.volBlock5 = volBlock5}} />
</div>
</div>
</div>
)
}
}
当然,如果您看到任何其他可以重构或改进我的代码的地方,我愿意接受建议。
使用 isMute
字段代替 isMuted
let muteToggle = null;
if(!this.state.isMute) {
muteToggle = <MdVolumeUp onClick={this.mute} />;
} else {
muteToggle = <MdVolumeOff onClick={this.mute} />;
}
我正在 React 中构建一个自定义音频播放器组件,我基于 this guide 和我自己的一些 modifications/additions。我遇到的问题是应该在常规音量图标和划掉的音量图标之间切换的 muteToggle 按钮没有更新。从功能上讲它可以工作,但在单击时似乎无法呈现相应的图标。
我对我应该做什么感到困惑,因为据我所知,我使用 play/pause 按钮的过程与 完全相同单击时更新。
我应该提一下,这个组件是用 GatsbyJS 构建的静态站点的一部分。
这是代码(其他一切都按预期工作):
import React from 'react'
import {MdPlayCircleOutline, MdPauseCircleOutline, MdVolumeOff, MdVolumeUp} from "react-icons/lib/md"
import '../styles/audioplayer.css'
export default class AudioPlayer extends React.Component {
constructor(props) {
super(props);
this.state = {
play: false,
lastVolume: this.volume5,
isMute: false
};
}
componentDidMount() {
this.audio.addEventListener("timeupdate", () => {
let ratio = this.audio.currentTime / this.audio.duration;
let position = (this.timeline.offsetWidth * ratio) + this.timeline.offsetLeft;
this.positionHandle(position);
});
}
positionHandle = (position) => {
let timelineWidth = this.timeline.offsetWidth - this.handle.offsetWidth;
let handleLeft = position - this.timeline.offsetLeft;
if (handleLeft >= 0 && handleLeft <= timelineWidth) {
this.handle.style.marginLeft = handleLeft + "px";
this.played.style.width = handleLeft + "px";
}
if (handleLeft < 0) {
this.handle.style.marginLeft = "0px";
this.played.style.width = "0px";
}
if (handleLeft > timelineWidth) {
this.handle.style.marginLeft = timelineWidth + "px";
this.played.style.width = timelineWidth + "px";
}
}
mouseMove = (e) => {
this.positionHandle(e.pageX);
this.audio.currentTime = ((e.pageX - this.timeline.offsetLeft) / this.timeline.offsetWidth) * this.audio.duration;
}
mouseUp = (e) => {
window.removeEventListener('mousemove', this.mouseMove);
window.removeEventListener('mouseup', this.mouseUp);
}
mouseDown = (e) => {
window.addEventListener('mousemove', this.mouseMove);
window.addEventListener('mouseup', this.mouseUp);
}
play = () => {
if (this.state.play) {
this.setState({ play: false });
this.audio.pause();
} else {
this.setState({ play: true });
this.audio.play();
}
}
mute = () => {
if (!this.state.isMute) {
this.audio.volume = 0;
this.setState({ isMute: true });
this.volBlock1.style.background = "#a4a4a4";
this.volBlock2.style.background = "#a4a4a4";
this.volBlock3.style.background = "#a4a4a4";
this.volBlock4.style.background = "#a4a4a4";
this.volBlock5.style.background = "#a4a4a4";
console.log("isMute: ", this.state.isMute);
} else {
this.setState({ isMute: false });
this.state.lastVolume();
console.log("isMute: ", this.state.isMute);
}
}
volume1 = () => {
this.audio.volume = 0.2;
this.setState({ lastVolume: this.volume1 });
this.volBlock1.style.background = "#000000";
this.volBlock2.style.background = "#a4a4a4";
this.volBlock3.style.background = "#a4a4a4";
this.volBlock4.style.background = "#a4a4a4";
this.volBlock5.style.background = "#a4a4a4";
}
volume2 = () => {
this.audio.volume = 0.4;
this.setState({ lastVolume: this.volume2 });
this.volBlock1.style.background = "#000000";
this.volBlock2.style.background = "#000000";
this.volBlock3.style.background = "#a4a4a4";
this.volBlock4.style.background = "#a4a4a4";
this.volBlock5.style.background = "#a4a4a4";
}
volume3 = () => {
this.audio.volume = 0.6;
this.setState({ lastVolume: this.volume3 });
this.volBlock1.style.background = "#000000";
this.volBlock2.style.background = "#000000";
this.volBlock3.style.background = "#000000";
this.volBlock4.style.background = "#a4a4a4";
this.volBlock5.style.background = "#a4a4a4";
}
volume4 = () => {
this.audio.volume = 0.8;
this.setState({ lastVolume: this.volume4 });
this.volBlock1.style.background = "#000000";
this.volBlock2.style.background = "#000000";
this.volBlock3.style.background = "#000000";
this.volBlock4.style.background = "#000000";
this.volBlock5.style.background = "#a4a4a4";
}
volume5 = () => {
this.audio.volume = 1;
this.setState({ lastVolume: this.volume5 });
this.volBlock1.style.background = "#000000";
this.volBlock2.style.background = "#000000";
this.volBlock3.style.background = "#000000";
this.volBlock4.style.background = "#000000";
this.volBlock5.style.background = "#000000";
}
render() {
let playButton = null;
if (!this.state.play) {
playButton = <MdPlayCircleOutline className="pButton" onClick={this.play} />
} else {
playButton= <MdPauseCircleOutline className="pButton" onClick={this.play} />
}
let muteToggle = null;
if(!this.state.isMuted) {
muteToggle = <MdVolumeUp onClick={this.mute} />;
} else {
muteToggle = <MdVolumeOff onClick={this.mute} />;
}
return(
<div id="audioplayer">
<audio id="music" ref={(audio) => { this.audio = audio } } controls>
<source src={this.props.audio} />
</audio>
{playButton}
<div id="timeline" onClick={this.mouseMove} ref={(timeline) => { this.timeline = timeline }}>
<div id="played" ref={(played) => {this.played = played}} />
<div id="handle" onMouseDown={this.mouseDown} ref={(handle) => { this.handle = handle }} />
</div>
<div className="volume-container">
{muteToggle}
<div className="volume-item" onClick={this.volume1} >
<div className="volume-block" ref={(volBlock1) => {this.volBlock1 = volBlock1}} />
</div>
<div className="volume-item" onClick={this.volume2} >
<div className="volume-block" ref={(volBlock2) => {this.volBlock2 = volBlock2}} />
</div>
<div className="volume-item" onClick={this.volume3} >
<div className="volume-block" ref={(volBlock3) => {this.volBlock3 = volBlock3}} />
</div>
<div className="volume-item" onClick={this.volume4} >
<div className="volume-block" ref={(volBlock4) => {this.volBlock4 = volBlock4}} />
</div>
<div className="volume-item" onClick={this.volume5} >
<div className="volume-block" ref={(volBlock5) => {this.volBlock5 = volBlock5}} />
</div>
</div>
</div>
)
}
}
当然,如果您看到任何其他可以重构或改进我的代码的地方,我愿意接受建议。
使用 isMute
字段代替 isMuted
let muteToggle = null;
if(!this.state.isMute) {
muteToggle = <MdVolumeUp onClick={this.mute} />;
} else {
muteToggle = <MdVolumeOff onClick={this.mute} />;
}