Fabdol
Fabdol

Reputation: 129

How should I fetch data onClick in Next js?

I have an input field plus a button next to it. I want to fetch data whenever the client presses the button.

I used SWR (I'm not sure if I have to use SWR or getServerSideProps method)

the problem is it fetches data when I refresh the page.

here is my code:

const fetcher = async () => {
    const res = await fetch(
      'https://eu-central-1.aws.webhooks.mongodb-realm.com/api/client/v2.0/app/lottigully-jjrda/service/movies/incoming_webhook/movies?arg=dexter'
    );
    const data = await res.json();
    return data;
  };

  const { data, error } = useSWR('uk', fetcher);
  if (error) {
    return 'there was an error';
  }
  if (!data) {
    return 'Loading';
  }

  console.log(data);


  return (
    <>
      <main>
        <div className={style.main_container}>
          <NavBar />
          <Hero />
        </div>
        <div className={style.search_container}>
          <SearchBar
            onChange={(e) => {
              setSearchTerm(e.target.value);
              console.log(searchTerm);
            }}
          />
        </div>
    <button onClick={?????}>Search!</button>

      </main>
    </>
  );
}

Upvotes: 6

Views: 6500

Answers (2)

brc-dd
brc-dd

Reputation: 13074

You can do something like this:

import { useState } from 'react';
import useSWR from 'swr';

const fetcher = (...args) => fetch(...args).then((res) => res.json());

const SearchResults = ({ keyword }) => {
  const { data, error } = useSWR(
    `https://eu-central-1.aws.webhooks.mongodb-realm.com/api/client/v2.0/app/lottigully-jjrda/service/movies/incoming_webhook/movies?arg=${keyword}`,
    fetcher
  );

  if (error) return <div>failed to load</div>;
  if (!data) return <div>loading...</div>;

  if (!data[0]) return <div>not found</div>;
  return <div>found {data[0].name}</div>;
};

const Home = () => {
  const [startFetching, setStartFetching] = useState(false);
  const [searchTerm, setSearchTerm] = useState('');

  const handleChange = (e) => {
    setStartFetching(false);
    setSearchTerm(e.target.value);
  };

  const handleClick = () => {
    setStartFetching(true);
  };

  return (
    <>
      <label for="series">Series: </label>
      <input type="text" value={searchTerm} onChange={handleChange} id="series" />{' '}
      <input type="submit" value="Search" onClick={handleClick} />
      <br />
      {startFetching && <SearchResults keyword={searchTerm} />}
    </>
  );
};

export default Home;

Basically, create a separate component that handles fetching and displaying UI based on the fetched content. And, create a state in the parent that tells when to render that component (and start fetching).

Credits: https://github.com/vercel/swr/issues/254

Upvotes: 4

oakar
oakar

Reputation: 1265

You should call mutate function that useSWR returns you.

const fetcher = async () => {
    const res = await fetch(
      'https://eu-central-1.aws.webhooks.mongodb-realm.com/api/client/v2.0/app/lottigully-jjrda/service/movies/incoming_webhook/movies?arg=dexter'
    );
    const data = await res.json();
    return data;
  };

  const { data, mutate, error } = useSWR('uk', fetcher);
  if (error) {
    return 'there was an error';
  }
  if (!data) {
    return 'Loading';
  }

  console.log(data);


  return (
    <>
      <main>
        <div className={style.main_container}>
          <NavBar />
          <Hero />
        </div>
        <div className={style.search_container}>
          <SearchBar
            onChange={(e) => {
              setSearchTerm(e.target.value);
              console.log(searchTerm);
            }}
          />
        </div>
    <button onClick={() => mutate()}>Search!</button>

      </main>
    </>
  );
}

Check this link please https://swr.vercel.app/docs/mutation

Upvotes: 1

Related Questions