【问题标题】:React state value is undefined反应状态值未定义
【发布时间】:2019-06-08 20:24:54
【问题描述】:

我正在构建一个音乐播放器应用程序,并且我有一个从处于组件状态的对象中获取值的函数。

当我将该值赋予函数时,它会打印 undefined 而不是值本身,因此该函数无法使用未定义的值。

这是我打印状态时 firstSong 组件的样子:

{
    Title: "One Dance",
    Artist: "Drake",
    Length: "4:03",
    Path:
      "/home/songs/Drake - One Dance ft. EMØ.mp3"
  }

这是完整的组件代码:

import React, { Component } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
  faBackward,
  faPlay,
  faForward,
  faStop
} from "@fortawesome/free-solid-svg-icons";
import styled from "styled-components";
import axios from "axios";

const CardStyling = styled.div`
  .card-body {
    width: 100%;
  }

  #song-header {
    margin-bottom: 25px;
  }

  #artist {
    margin-bottom: 25px;
  }

  #time {
    margin-bottom: 25px;
  }
`;

let display = "none";
const firstSongApi = "http://localhost:4001/getFirstSong";
const playSongApi = "http://localhost:4001/playSong";

export default class SongInfo extends Component {
  constructor() {
    super();
    this.state = {
      firstSong: this.getFirstSong(firstSongApi),
      isPlaying: false
    };
  }

  getFirstSong = async firstSongApi => {
    const request = await axios({
      method: "get",
      url: firstSongApi,
      headers: {}
    });
    try {
      let firstSong = request.data.firstSong;
      this.setState({
        firstSong: firstSong
      });
    } catch (error) {
      console.error(error);
    }
  };

  playOrPauseSong = path => {
    console.log(path);
  };

  render() {
    {
      this.playOrPauseSong(this.state.firstSong.path);
    }
    return (
      <CardStyling className="card">
        <div className="card-body">
          <h3 id="song-header">{this.state.firstSong.Title}</h3>
          <h5 id="artist">By: {this.state.firstSong.Artist}</h5>
          <h5 id="Time">{this.state.firstSong.Length}</h5>
          <button type="button" id="back-btn" className="btn">
            <FontAwesomeIcon icon={faBackward} />
          </button>
          <button
            type="button"
            id="play-btn"
            className="btn"
            onClick={() => this.playOrPauseSong(this.state.songLocation)}
          >
            <FontAwesomeIcon icon={faPlay} />
          </button>
          <button
            type="button"
            id="stop-btn"
            className="btn"
            style={{ display: display }}
          >
            <FontAwesomeIcon icon={faStop} />
          </button>
          <button type="button" id="next-btn" className="btn">
            <FontAwesomeIcon icon={faForward} />
          </button>
        </div>
      </CardStyling>
    );
  }
}


我希望函数获取真正的路径值而不是未定义,提前谢谢!

【问题讨论】:

  • 你能分享完整的组件吗
  • 给我介绍一下 firstSong 在 state 中的样子,可能你没有在构造函数或任何地方创建 state,还显示调用 this.playOrPauseSong(song) 的函数
  • 我已经发布了完整的组件代码,谢谢!

标签: javascript reactjs state


【解决方案1】:

确保您的状态如下所示,并且路径将在 playOrPauseSong 中正确记录;

    this.state = {
      firstSong: {
        title: "One Dance",
        artist: "Drake",
        length: "4:03",
        path:
          "/home/songs/Drake - One Dance ft. EMØ.mp3"
      }
    }


  playOrPauseSong = path => {
    console.log(path)
  }

  render(){

    return(
      <div>
        {this.playOrPauseSong(this.state.firstSong.path)}
      </div>
    )
  }

【讨论】:

  • 抱歉,它没有用,它打印我:./src/Components/SongInfo.js 语法错误:相邻的 JSX 元素必须包含在封闭标记中。你想要一个 JSX 片段 ...> 吗? (81:7) 79 | {this.playOrPauseSong(this.state.firstSong.path)} 80 |
    > 81 | | ^ 82 |
    83 |

    {this.state.firstSong.Title}

    84 |
    作者:{this.state.firstSong.Artist}
  • @nadavatar 这意味着您必须将元素包装在父 div 中或使用片段。
【解决方案2】:
render() {
    {
      this.playOrPauseSong(this.state.firstSong.path);
    }
...

未定义的原因是您的firstSong 仍在接受async 方法的网络请求,因此不会有任何firstSongfirstSong.path,因此它是undefined。因此,您可以更新为关注

render() {
    {
      this.state.firstSong.path && this.playOrPauseSong(this.state.firstSong.path);
    }

所以它的作用是,当没有path 时,该方法不会被调用,当你的网络调用返回结果时它会被调用,但实际上,你应该引入另一个标志来跳过调用this.playOrPauseSong 因为您的组件将不断重新渲染,并且您不想在每次重新渲染时都继续调用它

更新:

让我们稍微重构一下

我们可以将firstSong的初始状态设置为null,我们单独调用getFirstSong,所以你的构造函数应该如下

constructor() {
  super();
  this.state = {
    firstSong: null,
    isPlaying: false
  };
  this.getFirstSong(firstSongApi);
}

然后,对于您的 render 方法,您将改为检查 firstSong,因为在初始加载时,firstSong 将为空,因此更新为以下内容

render() {
    {
      this.state.firstSong && this.playOrPauseSong(this.state.firstSong.path);
    }

【讨论】:

  • 首先感谢您的回答,但是现在当我像您上面提到的那样调用该函数时,该函数甚至都没有被调用。
  • @nadavatar:这出乎意料,你能不能在getFirstSong 中做一个console.log 以确保它被调用?
  • @nadavatar:试试我更新的代码部分
  • 它打印出以下错误:TypeError: Cannot read property 'path' of null
  • @nadavatar:那是因为我们需要检查 this.state.firstSongrender 方法
猜你喜欢
  • 2020-08-20
  • 2021-03-05
  • 1970-01-01
  • 2020-09-24
  • 2018-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多