Search code examples
javascriptreactjsnext.jsreact-props

How to filter props in Next.js? Can't filter data in props from componentDidMount in Next.js


I get data into the props of my component by using getStaticProps. I then want to filter that data before I use it in the component. Usually I'd do this in componentDidMount, but that's not possible as it seems like the props are populated after componentDidMount is called.

What's the best practice for working around this?

Here's my current code:

class Definition extends Component {
  constructor({ router }, ...props) {
    super(props);
    this.state = {
      songsArray: [],
    };
  }

  filterSpotifyResults = () => {
    const filteredArray = [];
    this.props.songsData.tracks.items.forEach((obj) => {
      if (obj.explicit === true) {
        return;
      } else {
        filteredArray.push(obj);
      }
    });
    this.setState({ songsArray: filteredArray });
  };

  componentDidMount = () => {
    this.filterSpotifyResults();
  };

  render() {
    if (this.props.router.isFallback) {
      return <h4>Loading...</h4>;
    }
    return (
      <div>
        <h3>this is where the definition will go</h3>
        <ul>
          {this.props.wordsData.definitions.map((obj, i) => (
            <li key={i}>{obj.definition}</li>
          ))}
        </ul>
        <iframe
          src={`https://open.spotify.com/embed/track/${this.props.songsData.tracks.items[0].id}`}
          width="300"
          height="380"
          allowtransparency="true"
          allow="encrypted-media"
        ></iframe>
      </div>
    );
  }
}

export default withRouter(Definition);

export async function getStaticProps(context) {
  const wordsRes = await fetch(
    `https://wordsapiv1.p.rapidapi.com/words/${context.params.word}/definitions`,
    {
      method: "GET",
      headers: {
        "x-rapidapi-key": process.env.NEXT_PUBLIC_DB_KEY,
        "x-rapidapi-host": "wordsapiv1.p.rapidapi.com",
      },
    }
  )
    .then((response) => {
      return response;
    })
    .catch((err) => {
      console.error(err);
    });
  const songsRes = await fetch(
    `https://api.spotify.com/v1/search?q=${context.params.word}&type=track`,
    {
      method: "GET",
      headers: {
        authorization:
          "Bearer " + process.env.NEXT_PUBLIC_ENV_SPOTIFY_ACCESS_TOKEN,
      },
    }
  )
    .then((response) => {
      return response;
    })
    .catch((err) => {
      console.error(err);
    });
  const wordsData = await wordsRes.json();
  const songsData = await songsRes.json();
  return {
    props: {
      wordsData,
      songsData,
      searchTerm: context.params.word,
    },
  };
}

Solution

  • Best practice would definitely be filtering the data on the server, already in your getStaticProps.

    So move the filtering there, and only return the data you actually want to use/render.