You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React组件无法条件渲染?猜歌词网站按钮点击无响应问题

问题分析与修复方案

核心问题

你的代码存在几个关键错误,导致点击按钮后内容不显示、状态更新异常:

  1. 事件处理函数choseArtist返回的JSX不会自动渲染,React组件的所有渲染逻辑必须放在render方法的返回值中
  2. 错误使用forceUpdate(),React状态更新后会自动触发重新渲染,无需手动调用
  3. getRandomLyric未绑定this,调用时会导致setState报错
  4. axios请求URL格式错误,路径参数前的冒号是多余的
  5. 未根据artistSelected状态进行条件渲染

分步修复

1. 重构choseArtist方法

去掉方法内的JSX返回,只负责更新状态,并在状态更新完成后调用获取歌词的方法:

choseArtist(artist_id) {
  this.setState({
    artist_id: artist_id,
    artistSelected: true
  }, () => {
    // 状态更新完成后调用获取歌词的方法
    this.getRandomLyric(artist_id);
  });
}

2. 绑定方法的this指向

在constructor中绑定getRandomLyric和choseArtist的this,避免调用时指向错误:

constructor(props) {
  super(props);
  this.state = {
    artist_id: "",
    lyric: "", 
    actualTrack: "", 
    userTrack: "",
    artistSelected: false
  };
  // 绑定方法的this指向
  this.getRandomLyric = this.getRandomLyric.bind(this);
  this.choseArtist = this.choseArtist.bind(this);
}

3. 修正axios请求URL并添加错误处理

去掉路径参数前的冒号,同时添加try/catch处理请求失败的情况:

async getRandomLyric(artist_id) {
  try {
    // 修正URL格式
    const response = await axios.get(`http://localhost:3000/randomlyric/${artist_id}`);
    this.setState({
      lyric: response.data.lyric, // axios响应数据默认存在response.data中,根据后端接口调整
      actualTrack: response.data.actualTrack
    });
  } catch (error) {
    console.error('获取歌词失败:', error);
    this.setState({ lyric: '获取歌词失败,请重试' });
  }
}

4. 在render中添加条件渲染

根据artistSelected状态,决定是否显示选择歌手后的内容:

render() {
  return (
    <div>
      <h1>Welcome to the Song Guessing Game!</h1> 
      <p> These are the rules of the game: </p>
      <p> First, you must pick whether you are Team Taylor or Team Kanye.</p>
      <p> After you pick your team, you will be presented with 5 random lyrics from your chosen artist.</p>
      <p> Your job is to guess which song each lyric is from. </p>
      <p> Good luck!</p>

      {/* 歌手选择区域 */}
      <div className = "team_taylor">
        <div>
          <img className = "artist_picture"
          src={taylorSwift} 
          alt="Taylor Swift" />
        </div>
        <div className = "artist_button">
          {/* 去掉forceUpdate,只调用choseArtist */}
          <button onClick={()=> this.choseArtist(TAYLOR_ID)}> Team Taylor</button>
        </div>
      </div>

      <div className = "team_kanye">
        <div>
          <img className = "artist_picture"
          src={kanyeWest} 
          alt="Kanye West"/>
        </div>
        <div className = "artist_button">
          <button onClick={()=> this.choseArtist(KANYE_ID)}> Team Kanye</button>
        </div>
      </div>

      {/* 选择歌手后的内容,条件渲染 */}
      {this.state.artistSelected && (
        <div>
          <p> Great! Now a random lyric from the artist you chose will be presented and</p>
          <p> you will have to guess which song this lyric is from. </p> 
          <p> Good luck! </p>

          <div>
            <p>What track is this lyric from: {this.state.lyric || '加载中...'} </p>
            <input 
              type = "text" 
              value={this.state.userTrack}
              onChange ={ (e) => {
                this.setState({userTrack: e.target.value})
              }}
            />
          </div>
        </div>
      )}
    </div>
  );
}

5. 移除无用方法

删除未实现的showLyrics方法。


完整修改后的代码

import axios from 'axios';
import React, {Component} from 'react'
import taylorSwift from './taylorswift.jpg';
import kanyeWest from './kanyewest.jpeg';

const TAYLOR_ID = "259675";
const KANYE_ID = "33091467";

class Game extends Component {
    constructor(props) {
        super(props);
        this.state = {
            artist_id: "",
            lyric: "", 
            actualTrack: "", 
            userTrack: "",
            artistSelected: false
        };
        // 绑定方法的this指向
        this.getRandomLyric = this.getRandomLyric.bind(this);
        this.choseArtist = this.choseArtist.bind(this);
    }

    async getRandomLyric(artist_id) {
        try {
            // 修正URL路径参数格式
            const response = await axios.get(`http://localhost:3000/randomlyric/${artist_id}`);
            this.setState({
                lyric: response.data.lyric,
                actualTrack: response.data.actualTrack
            });
        } catch (error) {
            console.error('获取歌词失败:', error);
            this.setState({ lyric: '获取歌词失败,请重试' });
        }
    }

    choseArtist(artist_id) {
        this.setState({
            artist_id: artist_id,
            artistSelected: true
        }, () => {
            // 状态更新完成后调用获取歌词方法
            this.getRandomLyric(artist_id);
        });
    }

    render() {
        return (
            <div>
                <h1>Welcome to the Song Guessing Game!</h1> 
                <p> These are the rules of the game: </p>
                <p> First, you must pick whether you are Team Taylor or Team Kanye.</p>
                <p> After you pick your team, you will be presented with 5 random lyrics from your chosen artist.</p>
                <p> Your job is to guess which song each lyric is from. </p>
                <p> Good luck!</p>

                <div className = "team_taylor">
                    <div>
                        <img className = "artist_picture"
                        src={taylorSwift} 
                        alt="Taylor Swift" />
                    </div>
                    <div className = "artist_button">
                        <button onClick={()=> this.choseArtist(TAYLOR_ID)}> Team Taylor</button>
                    </div>
                </div>

                <div className = "team_kanye">
                    <div>
                        <img className = "artist_picture"
                        src={kanyeWest} 
                        alt="Kanye West"/>
                    </div>
                    <div className = "artist_button">
                        <button onClick={()=> this.choseArtist(KANYE_ID)}> Team Kanye</button>
                    </div>
                </div>

                {/* 条件渲染选择歌手后的内容 */}
                {this.state.artistSelected && (
                    <div>
                        <p> Great! Now a random lyric from the artist you chose will be presented and</p>
                        <p> you will have to guess which song this lyric is from. </p> 
                        <p> Good luck! </p>

                        <div>
                            <p>What track is this lyric from: {this.state.lyric || '加载中...'} </p>
                            <input 
                                type = "text" 
                                value={this.state.userTrack}
                                onChange ={ (e) => {
                                    this.setState({userTrack: e.target.value})
                                }}
                            />
                        </div>
                    </div>
                )}
            </div>
        );
    }
}

export default Game;

关键知识点说明

  1. React状态更新:setState是异步操作,如需在状态更新后执行逻辑,要使用setState(updater, callback)的回调函数
  2. 方法绑定:类组件中的方法默认不会绑定this,需在constructor中手动绑定,或使用箭头函数定义方法
  3. 条件渲染:通过{条件 && JSX}的方式,仅当条件为true时渲染对应JSX内容
  4. axios响应处理:axios的响应数据存于response.data中,需根据后端接口返回结构提取数据

内容的提问来源于stack exchange,提问作者Neelasha Bhattacharjee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 19:15:43