Search code examples
javascriptjsonreactjsnext.jsspread-syntax

manipulating/filtering objects' props from an API with spread operator


Doing a React/Next course, in a momment we had to fetch an API returning a list of objects, with data to fill the page.

It is done on Next's getStaticProps, and passed to frontend as props, manipulating some of the data to best fit, and ignoring some too. But to pass in a bunch os props that was not touched, required some extra typing:

data.map(episode=>{
    return {
      id: episode.id,
      title: episode.title,
      thumbnail: episode.thumbnail,
      members: episode.title,
      description: episode.description,
      url: episode.file.url,

      publishedAt: format( parseISO(episode.published_at), 'd MMM yy', {locale: ptBR } ),
      duration: Number(episode.file.duration),
      durationAsString: convertDurationToTimeString( Number(episode.file.duration) ),
    };
})

So i though of using JS's spread operation to make this code short, and less words hungry. But i'm afraid of this aproach having any impact on performance, readability, code maintainability / test, all of those things. Cause it doen't look a hard thing to come up with, so if the teacher didn'd do it, i may have some problem right?!

So please, take a look at this code, and say if is indeed a better solution, there's a problem in there:

const episodes = data.map(episode=>{
    const {
      file,
      published_at: publishedAt,
      ...rest

    } = episode;

    return {
      ...rest,
      url: file.url,
      duration: Number(file.duration),
      publishedAt: format( parseISO(publishedAt), 'd MMM yy', {locale: ptBR } ),
      durationAsString: convertDurationToTimeString( Number(file.duration) ),
    }
}


Here it is with line comments if it helps unsderstant what it means:

const episodes = data.map(episode=>{

    // filter out the data
    const {
      // attrs to remove from final
      file,

      // . to rename
      published_at: publishedAt,

      // to keep as is
      ...rest

    } = episode;

    // threat/manipulate and add data
    return {
      ...rest,
      url: file.url,
      duration: Number(file.duration),
      publishedAt: format( parseISO(publishedAt), 'd MMM yy', {locale: ptBR } ),
      durationAsString: convertDurationToTimeString( Number(file.duration) ),
    }
}


Solution

  • const episodes = data.map(({ file, published_at: publishedAt, ...rest }) => ({
      ...rest,
      url: file.url,
      duration: Number(file.duration),
      publishedAt: format(parseISO(publishedAt), 'd MMM yy', { locale: ptBR }),
      durationAsString: convertDurationToTimeString(Number(file.duration)),
    }));
    

    This is the cleanest way I can suggest but your own code was readable enough and there is no performance cost in spreading objects as far as I know.