Reputation: 93
I have a Header component which updates url parameters to make an api call, and uses next router to pass these parameters to the results page.
I want to be able to search again from this page using router, but the page does not refresh due to the results page being the same.
How can I acheive this?
Many thanks for any help, code below.
Header.js
import { useState, useEffect, useContext } from "react";
import { useRouter } from "next/router";
export default function Header() {
const [searchText, setSearchText] = useState("");
const [impact, setImpact] = useState("");
const [worldwide, setWorldwide] = useState(false);
const router = useRouter();
const onClick = (e) => {
setWorldwide(e.target.checked);
};
const handleSubmit = (event) => {
event.preventDefault();
setImpact(impact);
let remote = "";
if (worldwide === true) {
remote = "Remote";
} else {
remote = "";
}
router.push({
pathname: `/remote-jobs`,
query: {
term: `${searchText}`,
impact: `${impact}`,
location: `${remote}`,
},
});
};
return (
<div>
<div className="p-4 flex flex-col items-center justify-center w-1/3 md:w-full">
<form onSubmit={handleSubmit}>
<select
onChange={(e) => setImpact(e.target.value)}
className="pl-2 pr-2 mr-4 h-10 rounded bg-white text-black md:h-12 md:pl-4 md:pr-4"
>
<option value="">choose an option</option>
<option value="sdg1">option1</option>
<option value="sdg2">option2</option>
</select>
<input
placeholder={"search"}
className="pl-2 pr-2 h-10 my-2 rounded bg-white text-black md:h-12 md:pl-4 md:pr-4"
onChange={(event) => {
setSearchText(event.target.value);
}}
/>
<button className="ml-4 pl-2 pr-2 rounded bg-black text-white md:h-12 md:pl-4 md:pr-4">
Go
</button>
<input
className="ml-4"
type="checkbox"
onClick={onClick}
value={!worldwide}
/>{" "}
</form>
</div>
</div>
</div>
);
}
Results page:
import React, { useState, useEffect } from "react";
import Job from "../components/Job";
import Header from "../components/Header";
export default function App(key) {
const [jobs, setJobs] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const urlParams = new URLSearchParams(window.location.search);
const searchTerm = urlParams.get("term");
const searchImpact = urlParams.get("impact");
const searchLocation = urlParams.get("location");
const fetchJobs = async () => {
const url = `https://api.app/api/search?term=${searchTerm}&impact=${searchImpact}&location=${searchLocation}`;
const response = await fetch(url);
const info = await response.json();
setLoading(false);
setJobs(info);
};
fetchJobs();
}, []);
return (
<div className="App">
<Header />
{loading ? (
<div>...loading</div>
) : (
<div>
{jobs.length} jobs
<div>
{jobs.map((job) => (
<Job job={job} key={job.id} />
))}
</div>
</div>
)}
</div>
);
}
Upvotes: 3
Views: 5413
Reputation: 81
You should use next router to get the query values and then you can useEffect to fetch new data whenever the query changes
export default function App(key) {
const [jobs, setJobs] = useState([]);
const [loading, setLoading] = useState(true);
const { query: { term, impact, location } } = useRouter();
useEffect(() => {
const fetchJobs = async () => {
const url = `https://api.app/api/search?term=${term}&impact=${impact}&location=${location}`;
const response = await fetch(url);
const info = await response.json();
setLoading(false);
setJobs(info);
};
fetchJobs();
}, [term, impact, location]);
return (
<div className="App">
<Header />
{loading ? (
<div>...loading</div>
) : (
<div>
{jobs.length} jobs
<div>
{jobs.map((job) => (
<Job job={job} key={job.id} />
))}
</div>
</div>
)}
</div>
);
}
Upvotes: 4