1

I´m new to NextJS and React at all so I ask for your forgiveness. I want to know how to pass an users written text from an input field (inside of Header) into the getStaticProbs function of a specific page via the react context api. I tried the following source but it doesn`t work - it throws out an error that my way to build leads to an invalid hook call.

Here is my context source:

import React, { createContext, useState } from 'react';

export const SearchContext = createContext();

export const SearchProvider = ({ children }) => {
  const [keyword, setKeyword] = useState('');

  return (
    <SearchContext.Provider
      value={{
        keyword,
        setKeyword,
      }}
    >
      {children}
    </SearchContext.Provider>
  );
};

to fetch the written string of SearchBar.js:

import React, { useContext, useState } from 'react';
import { useRouter } from 'next/router';
import Image from 'next/image';
import loupe from '../public/images/loupe.png';
import { SearchContext } from '../lib/searchCtx';

const SearchBar = () => {
  const search = useContext(SearchContext);

  const router = useRouter();

  const submitAction = (e) => {
    e.preventDefault();
    router.push(`/searchResults`);
  };

  return (
    <div className={styles.searchBar}>
      <input
        type='text'
        placeholder='Suche...'
        onChange={(e) => search.setKeyword(e.target.value)}
      />
      <button className={styles.searchBtn} type='submit' onClick={submitAction}>
        <Image src={loupe} alt='' />
      </button>
    </div>
  );
};

export default SearchBar;

and pass it over _app.js:

import Header from '../components/Header';
import Footer from '../components/Footer';
import { SearchProvider } from '../lib/searchCtx';

function MyApp({ Component, pageProps }) {

    return (
      <>
        <SearchProvider>
          <Header />
          <Component {...pageProps} />
        </SearchProvider>
        <Footer />
      </>
    );
  }
}

export default MyApp;

to get the value into getStaticProbs of searchResults.js:

import { useEffect, useState, useContext } from 'react';
import { fetchData } from '../lib/utils';
import styles from '../styles/Playlist.module.scss';
import Image from 'next/image';
import { SearchContext } from '../lib/searchCtx';

export default function SearchResults({ videos }) {
  console.log(videos);

  const sortedVids = videos
    .sort((a, b) =>
      Number(
        new Date(b.snippet.videoPublishedAt) -
          Number(new Date(a.snippet.videoPublishedAt))
      )
    )

  return (
    <>
      <div className={`${styles.playlist_container} ${styles.search}`}>
            <h1>Search results</h1>      
          {sortedVids
            .map((vid, id) => {
              return (
                  <div className={styles.clip_container}>
                    <Image
                      className={styles.thumbnails}
                      src={vid.snippet.thumbnails.medium.url}
                      layout='fill'
                      objectFit='cover'
                      alt={vid.snippet.title}
                    />
                  </div>
                  <div className={styles.details_container}>
                    <h3>{vid.snippet.title}</h3>
                  </div>
              );
            })}
      </div>
    </>
  );
}

export async function getStaticProps() {
  const search = useContext(SearchContext);

  const { YOUTUBE_KEY } = process.env;
  const uploadsURL = `https://youtube.googleapis.com/youtube/v3/search?part=snippet&channelId=UCbqKKcML7P4b4BDhaqdh_DA&maxResults=50&key=${YOUTUBE_KEY}&q=${search.keyword}`;

  async function getData() {
    const uploadsData = fetchData(uploadsURL);

    return {
      videos: await uploadsData,
    };
  }

  const { videos } = await getData();
  return {
    revalidate: 86400,
    props: {
      videos: videos.items,
    },
  };
}

Would you help me by 1) telling me the main failure I did and 2) providing me a working source? How can I achieve it to get the keyword from SearchContext into the uploadsURL (inside of getStaticProbs) or isn`t it possible? Thanks in advance!!

Ydonut13
  • 47
  • 1
  • 11
  • 2
    Read next.js docs, `getStaticProps` runs at **build time** you cant pass props to it. – Nico Sep 06 '21 at 14:04
  • @Nico What would you do instead to get the value into uploadsURL to get the right results for users search? – Ydonut13 Sep 06 '21 at 14:18

1 Answers1

0

You can create a dynamic pages under your page folder one called say index.js and one called [slug].js (all under one folder) In the index page you can have your normal search input, when the users submit the query you can do

<a
  onClick={() =>
   router
    .push(`/movies/${search.keyword}`)
    .then(() => window.scrollTo(0, 0))}>
   search
 </a>

and in your [slug].js page you can retrieve that information like so

export async function getServerSideProps(pageContext) {
  const pageQuery = pageContext.query.slug;
  const apiCall= await fetch(
    ``https://youtube.googleapis.com/youtube/v3/search?part=snippet&channelId=UCbqKKcML7P4b4BDhaqdh_DA&maxResults=50&key=${YOUTUBE_KEY}&q=${pageQuery}`
  );

  const results = await apiCall.json();

  return {
    props: {
      data: results,
    },
  };
}

I don't know if this will work for you but is a solution

Vincenzo
  • 375
  • 3
  • 15