首页 > 解决方案 > 将 React 类组件转换为功能组件,完美渲染但功能丢失?

问题描述

我正在制作一个小型音频播放器应用程序并尝试将我的反应类组件转换为功能组件。

类组件的原始代码在这里:

class Player extends React.Component {

    constructor(){
    super()

    this.state = {
        tracks: [
          {title: "first track", data: track1},
          {title: "second track", data: track2},
          {title: "third track", data: track3},
        ],
        currentTrack: 0,
    }

    }

     changeData(trackIndex){
      this.setState({currentTrack: trackIndex})
    }
  
    render(){
        return <div style={{color: this.props.color}}>
            <h1>Player</h1>
           <AudioPlayer
            src= {this.state.tracks[this.state.currentTrack].data}
            />
            <div style={{color: "green"}}>
                <ul>
                    {this.state.tracks.map((trackElem, index) => (
                       <li onClick={()=> this.changeData(index)}>{trackElem.title}</li>
                    ))}
                </ul>
            </div>
        </div>
    }
}

我尝试了以下转换:

const Player2 = () => {

   const Items = [
          {title: "first track", data: track1},
          {title: "second track", data: track2},
          {title: "third track", data: track3},
    ]; 

    const [activeTrack, setActiveTrack] = useState(0);

    function ChangeData(trackIndex) {
        setActiveTrack({activeTrack : trackIndex});
    }

    return (
        <div >
           <h1>Player</h1>
           <AudioPlayer
            src= {activeTrack.data}
            />
            <div >
                <ul>
                    {Items.map((trackElem, index) => (
                       <li onClick={()=> ChangeData(index)}>{trackElem.title}</li>
                    ))}
                </ul>
            </div>
        </div>
    )
}

除了删除一些与样式相关的道具之外,逻辑基本相同。唯一的区别是当前轨道的处理,我试图通过使用状态来表示这一点。

当将对象渲染到不同的页面时,它在屏幕上看起来完全正常,唯一的问题是轨道本身不再触发音频播放器中的响应。

如果有人能找出我在转换过程中遗漏的任何东西,真的会很感激吗?

标签: javascriptreactjsreact-hooksreact-class-based-component

解决方案


这里:

const [activeTrack, setActiveTrack] = useState(0);

最初状态activeTrack中的数字也是如此。但是你这样做了

src= {activeTrack.data}

这是没有意义的——这个数字没有data属性。另一个问题是

setActiveTrack({activeTrack : trackIndex});

现在您将活动轨道设置为具有activeTrack属性的对象,这也与上述两种格式不同。

选择一种方式来表示、设置和检索整个组件的状态,例如索引:

function ChangeData(trackIndex) {
    setActiveTrack(trackIndex);
}
<AudioPlayer
    src={Items[activeTrack].data}

推荐阅读