Reputation: 129
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
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
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