簡體   English   中英

State JSX 組件未更新

[英]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;```

不要在 state 中存儲 jsx

只需將 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM