user2095430
user2095430

Reputation: 93

nextjs router update on URL parameter change

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

Answers (1)

RaCzO
RaCzO

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

Related Questions