ReactJS - How to assign an JSX element to a variable and use it in render method

Hi Campers! Recently I’m working on this project of a music player and I have a Class Component “MuscicPlayer”, which has a render method like this:

render() {
        let nowPlayingSong = this.state.songList.getSongAtIndex(this.state.nowPlayingSongIndex);
        let nowPlayingSongURL = nowPlayingSong.songURL;
        let nowPlayingSongAlbumArt = nowPlayingSong.songAlbumArtLink;
        let nowPlayingSongTitle = nowPlayingSong.songTitle;
        let nowPlayingSongAuthor = nowPlayingSong.songAuthor;

        if (this.state.isShowingNowPlayingBoard === true)
            return (
                <div id="music-player">
                <SongInfo 
                    albumArt={nowPlayingSongAlbumArt}
                    songTitle={nowPlayingSongTitle}
                    songAuthor={nowPlayingSongAuthor}
                    currentTime={this.convertSecondToMinute(this.state.currentTime)}
                    duration={this.convertSecondToMinute(this.state.nowPlayingSongDuration)} />;
                <audio 
                    src={nowPlayingSongURL} 
                    id="audio">
                </audio>
                <Scrubber percent={this.state.percent} />
                <ControlPanel 
                    handlePlayPause={this.handlePlayPause}
                    handleNext={this.handleNext}
                    handlePrevious={this.handlePrevious}
                    handleShuffle={this.handleShuffle}
                    handleToggleNowPlayingBoard={this.handleToggleNowPlayingBoard} />
                <NowPlayingBoard 
                    songList={this.state.songList.songList} 
                    toggleShowing={this.handleToggleNowPlayingBoard}
                    removeSong={this.handleRemoveSong}
                    isPause={this.state.isPause} />
            </div>
            );
        else return (
            <div id="music-player">
                <SongInfo 
                    albumArt={nowPlayingSongAlbumArt}
                    songTitle={nowPlayingSongTitle}
                    songAuthor={nowPlayingSongAuthor}
                    currentTime={this.convertSecondToMinute(this.state.currentTime)}
                    duration={this.convertSecondToMinute(this.state.nowPlayingSongDuration)} />
                <audio 
                    src={nowPlayingSongURL} 
                    id="audio">
                </audio>
                <Scrubber percent={this.state.percent} />
                <ControlPanel 
                    handlePlayPause={this.handlePlayPause}
                    handleNext={this.handleNext}
                    handlePrevious={this.handlePrevious}
                    handleShuffle={this.handleShuffle}
                    handleToggleNowPlayingBoard={this.handleToggleNowPlayingBoard}
                    isPause={this.state.isPause} />
            </div>
        );
    }

As you can see, in the render method, I have an if-else statement and inside I have some functional components. But the problem is the duplication in my code, I have tried assign the duplicated components to variables before the return statement and reuse them inside the return but It just doesn’t work, this is how I tried:

render() {
        let nowPlayingSong = this.state.songList.getSongAtIndex(this.state.nowPlayingSongIndex);
        let nowPlayingSongURL = nowPlayingSong.songURL;
        let nowPlayingSongAlbumArt = nowPlayingSong.songAlbumArtLink;
        let nowPlayingSongTitle = nowPlayingSong.songTitle;
        let nowPlayingSongAuthor = nowPlayingSong.songAuthor;
        **let songInfo = <SongInfo **
**                    albumArt={nowPlayingSongAlbumArt}**
**                    songTitle={nowPlayingSongTitle}**
**                    songAuthor={nowPlayingSongAuthor}**
**                    currentTime={this.convertSecondToMinute(this.state.currentTime)}**
**                    duration={this.convertSecondToMinute(this.state.nowPlayingSongDuration)} />;**
**        let controlPanel =  <ControlPanel **
**                    handlePlayPause={this.handlePlayPause}**
**                    handleNext={this.handleNext}**
**                    handlePrevious={this.handlePrevious}**
**                    handleShuffle={this.handleShuffle}**
**                    handleToggleNowPlayingBoard={this.handleToggleNowPlayingBoard} />;**

        if (this.state.isShowingNowPlayingBoard === true)
            return (
                <div id="music-player">
                **{songInfo}**
                <audio 
                    src={nowPlayingSongURL} 
                    id="audio">
                </audio>
                <Scrubber percent={this.state.percent} />
                **{controlPanel}**
                <NowPlayingBoard 
                    songList={this.state.songList.songList} 
                    toggleShowing={this.handleToggleNowPlayingBoard}
                    removeSong={this.handleRemoveSong}
                    isPause={this.state.isPause} />
            </div>
            );
        else return (
            <div id="music-player">
                **{songInfo}**
                <audio 
                    src={nowPlayingSongURL} 
                    id="audio">
                </audio>
                <Scrubber percent={this.state.percent} />
                **{controlPanel}**
            </div>
        );
    }

Could you show me the way to refactor my code so that it would be less duplicated? Thank you very much?

To refactor I would suggest having just one return block and have conditionals only on the things that are different. If I read it correctly it seems like the big difference is is the NowPlayingBoard? Maybe just have that set inside an inline conditional like the example randel linked above.

Another thing that could possibly be improved in a refactor might be breaking the song information down in a lower level, and passing down less props at this level.

1 Like

adding my voice to @Lucasl and @camperextraordinaire you should benefit from es6 syntax to write and read your code easily and use a simpler variable names , you also could use what is like jsx variable in your component and use it in you render method but I suggest using @Lucasl solution in this example but if you want to do it in other components when needed

class ReactCompnent extends Component {

renderSomeJSX() {
return <Jsx />;
}

render() {
 retrun (
    <AnotherJsx />
     {//use the method as a variable be calling it}
     {this.renderSomeJSX()}
 );
}

}