2

I'm having this issue where my .map won't update any of my data when it rerenders. I have a simple player that is moving to the next element in the playlist array and after its updated or every time I click next or prev in my Playerbar it supposed to show Artist of the selected song {artist.name} and the Selected song {song.name} but for some reason nothing changes. I think I have missed something obvious but can't see it Can someone help me out please? Thanks.

const PlayerBar = (props) => {
  const [playing, setPlaying] = React.useState(false);

  function clickPlayButton() {
    setPlaying(!playing)
  }

  function renderPlayButton() {
    let buttonUrl = '';
    if (playing) {
      buttonUrl = 'https://codesignal.s3.amazonaws.com/uploads/1557137524244/rounded-pause-button.svg';
    } else {
      buttonUrl = 'https://codesignal.s3.amazonaws.com/uploads/1557136695174/play-right-arrow-circular-button.svg';
    }
    return (
      <input
        id="playPause"
        className="play-button"
        type="image"
        src={buttonUrl}
        onClick={() => clickPlayButton()}
      />
    );
  }

  function renderNextButton() {
    let buttonUrl = 'https://codesignal.s3.amazonaws.com/uploads/1557137539567/next-button.svg';
    return (
      <input
        id="next"
        className="play-button" 
        type="image" 
        src={buttonUrl} 
        onClick={() => props.nextButton()}
      />
    );
  };

  function renderPrevButton() {
    let buttonUrl = 'https://codesignal.s3.amazonaws.com/uploads/1557138446191/previous-button.svg';
    return (
      <input
        id="prev"
        className="play-button" 
        type="image"  
        src={buttonUrl} 
        onClick={() => props.prevButton()}
      />
    );
  };

  return (
      <div>
        {renderPlayButton()}
        {renderPrevButton()}
        {renderNextButton()}
        
        <div className="song-descr">
          <span className="song-artist song-span">Artist of the selected song</span>
          <span className="song-name song-span">Selected song name</span>
        </div>
      </div>
  );
}

const App = () => {
  const playlist = [
      {
        id: 1,
        name: 'Yesterday',
        artist: 'Beatles'
      },
      {
        id: 2,
        name: 'Nothing else matters',
        artist: 'Metallica'
      },
      {
        id: 3,
        name: 'Always',
        artist: 'Bon Jovi'
      },
      {
        id: 4,
        name: 'Waka Waka',
        artist: 'Shakira'
      }
    ];

  const [curItemIndex, setCurItemIndex] = React.useState(0);
    const [list, setPlaylist] = React.useState(playlist)

    
  function getSongClass(index) {
    let className = 'list-group-song song row';
    if (index === curItemIndex) {
      className += ' selected';
    }
    return className;
  }

  function renderItems() {
    return list.map((song, index) => {
      return (
        <li className={getSongClass(index)} key={song.id}>
          <span className="song-artist song-span">{song.artist}</span>
          <span className="song-name song-span">{song.name}</span>
        </li>
      );
    });
  }

  function clickNextButton() {
    if(curItemIndex === curItemIndex.length - 1)
        return;
        
    setCurItemIndex(curItemIndex => curItemIndex + 1)

  }

  function clickPrevButton() {
     if(curItemIndex === 0)
        return;
        
    setCurItemIndex(curItemIndex => curItemIndex - 1)
  }

  return (
    <div>
      <ul className="song-list container">
        {renderItems()}
      </ul>
      <hr />
      <div className="player-bar">
        <PlayerBar
          nextButton={clickNextButton}
          prevButton={clickPrevButton}
        />
      </div>
    </div>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById('app')
);
6
  • Fat arrow => already has a return statement implicitly present, so you don't need to add return after that. Try removing return from your renderItems() function. Commented Mar 9, 2021 at 12:43
  • You did not pass list to the children component PlayerBar using props. You have to add some more props in PlayerBar component: exactly selected list data according to selected item number. Commented Mar 9, 2021 at 12:49
  • @ArtemMedianyk can you explain what you mean by that in an answer please? Commented Mar 9, 2021 at 12:52
  • ok, I will add my answer soon Commented Mar 9, 2021 at 12:53
  • if(curItemIndex === curItemIndex.length - 1) should be if(curItemIndex === list.length - 1) right? Commented Mar 9, 2021 at 13:26

1 Answer 1

2
const PlayerBar = (props) => {
  const [playing, setPlaying] = React.useState(false);

  function clickPlayButton() {
    setPlaying(!playing)
  }

  function renderPlayButton() {
    let buttonUrl = '';
    if (playing) {
      buttonUrl = 'https://codesignal.s3.amazonaws.com/uploads/1557137524244/rounded-pause-button.svg';
    } else {
      buttonUrl = 'https://codesignal.s3.amazonaws.com/uploads/1557136695174/play-right-arrow-circular-button.svg';
    }
    return (
      <input
        id="playPause"
        className="play-button"
        type="image"
        src={buttonUrl}
        onClick={() => clickPlayButton()}
      />
    );
  }

  function renderNextButton() {
    let buttonUrl = 'https://codesignal.s3.amazonaws.com/uploads/1557137539567/next-button.svg';
    return (
      <input
        id="next"
        className="play-button" 
        type="image" 
        src={buttonUrl} 
        onClick={() => props.nextButton()}
      />
    );
  };

  function renderPrevButton() {
    let buttonUrl = 'https://codesignal.s3.amazonaws.com/uploads/1557138446191/previous-button.svg';
    return (
      <input
        id="prev"
        className="play-button" 
        type="image"  
        src={buttonUrl} 
        onClick={() => props.prevButton()}
      />
    );
  };

  return (
      <div>
        {renderPlayButton()}
        {renderPrevButton()}
        {renderNextButton()}
        
        <div className="song-descr" id={props.listId}>
          <span className="song-artist song-span">{props.listArtist}</span> // here ...
          <span className="song-name song-span">{props.listName}</span> // here ...
        </div>
      </div>
  );
}



const App = () => {
  const playlist = [
      {
        id: 1,
        name: 'Yesterday',
        artist: 'Beatles'
      },
      {
        id: 2,
        name: 'Nothing else matters',
        artist: 'Metallica'
      },
      {
        id: 3,
        name: 'Always',
        artist: 'Bon Jovi'
      },
      {
        id: 4,
        name: 'Waka Waka',
        artist: 'Shakira'
      }
    ];

  const [curItemIndex, setCurItemIndex] = React.useState(0);
    const [list, setPlaylist] = React.useState(playlist)

    
  function getSongClass(index) {
    let className = 'list-group-song song row';
    if (index === curItemIndex) {
      className += ' selected';
    }
    return className;
  }

  function renderItems() {
    return list.map((song, index) => {
      return (
        <li className={getSongClass(index)} key={song.id}>
          <span className="song-artist song-span">{song.artist}</span>
          <span className="song-name song-span">{song.name}</span>
        </li>
      );
    });
  }

  function clickNextButton() {
    if(curItemIndex === list.length - 1) // here ...
        return;
        
    setCurItemIndex(curItemIndex => curItemIndex + 1)

  }

  function clickPrevButton() {
     if(curItemIndex === 0)
        return;
        
    setCurItemIndex(curItemIndex => curItemIndex - 1)
  }

  return (
    <div>
      <ul className="song-list container">
        {renderItems()}
      </ul>
      <hr />
      <div className="player-bar">
        <PlayerBar
          nextButton={clickNextButton}
          prevButton={clickPrevButton}
          listId={list[curItemIndex].id} // here ...
          listName={list[curItemIndex].name} // here ...
          listArtist={list[curItemIndex].artist} // here ../
        />
      </div>
    </div>
  );
}


ReactDOM.render(
  <App />,
  document.getElementById('app')
);

Please try this. I changed only 6 lines

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.