requestgetserver-side-renderingdenofreshjs

In fresh app (similar to nextjs for deno) I can't get an API call to wait for a button push. It runs on page load


I am making a Fresh app (which is a next-gen web framework that works with Deno). I understand the structure of the app and how it handles routing and I made a modified version of the search page from the fresh website https://fresh.deno.dev/docs/getting-started/form-submissions.

// routes/search.tsx
import Layout from '../components/layouts.tsx';
import { Handlers, PageProps } from "$fresh/server.ts";

const NAMES = ["Alice", "Bob", "Charlie", "Dave", "Eve", "Frank"];

interface Data {
  results: string[];
  query: string;
}

export const handler: Handlers<Data> = {
  GET(req, ctx) {
    const url = new URL(req.url);
    const query = url.searchParams.get("q") || "";
    const results = NAMES.filter((name) => name.includes(query));
    return ctx.render({ results, query });
  },
};

export default function Page({ data }: PageProps<Data>) {
  const { results, query } = data;
  return (
    <Layout>
      <form>
        <h1 class="text rounded-lg p-4 my-8"> Search </h1>
        <input class="center rounded-lg p-4 my-8" type="text" name="q" value={query} />
        <br />
        <button
            class="px-5 py-2.5 text-sm font-medium bg-blue-600 rounded-md shadow disabled:(bg-gray-800 border border-blue-600 opacity-50 cursor-not-allowed)"
            type="submit">Submit
        </button>
      </form>
      <br />
      <ul>
        {results.map((name) => <li key={name}>{name}</li>)}
      </ul>
    </Layout>
  );
}

But the problem is that the search function runs before I click the button. On page load, all of const NAMES are printed on the webpage.
enter image description here

So how do I make the app wait until I push submit to do a search?

P.S. I navigated to localhost:8000/search in the url bar, it redirected to http://localhost:8000/search?q= because as soon as I hit enter the search funtion runs.


Solution

  • It is because when the search term is not set in the url then query is set to an empty string. Therefore results is filtered on an empty string so it returns all the results.

    A solution would be to return an empty results array if the query is not supplied.

    export const handler: Handlers<Data> = {
      GET(req, ctx) {
        const url = new URL(req.url);
        const query = url.searchParams.get("q") || "";
        // const results = NAMES.filter((name) => name.includes(query));
        let results: string[];
        if (query === "") {
          results = [];
        } else {
          results = NAMES.filter((name) => name.includes(query));
        }
        return ctx.render({ results, query });
      },
    };