0

I got a technical assessment that I've been messing with but can't get working. I need to get this HTML form working. The API call has to be done on the backend using isomorphic-fetch, their rules. What needs to happen to meet MVP I guess is that form needs to send the backend the search term, the backend needs to call the dog API for a photo of the dog from the search term, and that data needs to be sent back to the front, and then displayed. Seems easy but I'm struggling to get it working. Any help would be appreciated, thank you. Even just some help getting these params passed from front to back would be awesome. I've used express but not koa, and that was over a year ago.

Here is the code.

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/water.css">
    <title>Lots of dogs! </title>
</head>
<body>
    <h1>Lots of dogs! </h1>
    <p>See photos of your favorite dogs</p>
    <form>
        <input type="text" name="breed" placeholder="Enter a dog breed">
        <button type="submit">Fetch</button>
    </form>
</body>
</html>




import Koa from "koa";
import Router from "@koa/router";
import cors from "@koa/cors";
import fetch from "isomorphic-fetch";

const app = new Koa();
const router = new Router();
const port = 3011;

app.use(cors({ origin: "*" }));

router.get("/", (ctx) => {
  ctx.body = "hello!";
});

app.use(async (ctx, next) => {
  await next();
  const rt = ctx.response.get("X-Response-Time");
  console.log(`${ctx.method} ${ctx.url} - ${rt}`);
});

app.use(async (ctx, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  ctx.set("X-Response-Time", `${ms}ms`);
});

router.get("/:searchTerm", async (ctx, next) => {
  const breed = req.params;
  console.log(`breed: ${breed}`);
});

const fetchBreedImage = () => {
  fetch("https://dog.ceo/api/breed/hound/images").then((data) =>
    console.log(data)
  );
};

app.use(router.routes());

app.listen(port, () => {
  console.log(`Server running on http://localhost:${port}`);
});
Brendan F
  • 19
  • 1
  • Where exactly are you stuck? What does not work? What did you expect to happen that doesn't happen? – Bergi Oct 15 '22 at 23:47
  • Hi, in `fetchBreedImage()` function, what exactly need to be filtered? – Lucas Paixão Oct 15 '22 at 23:51
  • "the backend the search term, the backend needs to call the dog API for a photo of the dog from the search term" ->> What is the URL to retrieve the photos for the specific search term? And, if the URL retrieve all photos, do you need to filter what exactly? Example: `https://dog.ceo/api/breed/hound/images` return an array of URls, with these URLs, what do you need to do? – Lucas Paixão Oct 15 '22 at 23:54
  • Any questions, please comment so I can edit my answer, I wish you success on your journey :) – Lucas Paixão Oct 16 '22 at 00:33
  • Nothing really, just me trying to call that dog API they referenced. The docs to the API are https://dog.ceo/dog-api/documentation/ that. Those are the two files, and they've already called the packages they want to use. Isomorphic-fetch on the backend, to that API, the form on the front needs to send that param to the back. Eventually, that data needs to get back to the front somehow to show and image. --- Also, I understand that's the API endpoint I need to call, and do anything I want with the images. The issue is passing it in the params to and from front/back with the form/koa server. – Brendan F Oct 16 '22 at 00:48
  • Passing the search term. So from the form on the frontend passing that param to the backend is what I need most help with, passing it back to the frontend after I make the API call, the API call itself is no issue, it's just getting it back in forth in the params I'm confused on the correct way to do. Thank you. – Brendan F Oct 16 '22 at 00:52

2 Answers2

1

The problem:


router.get("/:searchTerm", async (ctx, next) => {
  const breed = req.params;
  console.log(`breed: ${breed}`);
});

The variable req is not declared in this context, do access the :searchTerm param, you need to use ctx.params.searchTerm

How to solve:


  1. First, you need to use ctx.params.searchTerm
  2. You need to pass the searchTerm the URL API: https://dog.ceo/api/breed/${searchTerm}/images
    const fetchBreedImage = breed =>
    fetch(`https://dog.ceo/api/breed/${breed}/images`)
       .then((res) => res.json())
       .catch((err) => console.log({ err }));
    
  3. You need to return the result of fetchBreedImage to the client:
    router.get("/search/:searchTerm", async (ctx, next) => {
    
        const { searchTerm } = ctx.params;
        const { message } = await fetchBreedImage(searchTerm);
        ctx.body = message;
    })
    

The final code:


Here is an example with the code applying all recommendations above.

import Koa from "koa";
import Router from "@koa/router";
import cors from "@koa/cors";
import fetch from "isomorphic-fetch";
import serve from "koa-static";

const app = new Koa();
const router = new Router();
const port = 8000;

const format = str =>
  str.toLowerCase()
     .replace(/\s/g, '');

app.use(cors({ origin: "*" }));

router.get("/", (ctx) => {
  ctx.body = "hello!";
});

app.use(async (ctx, next) => {
  await next();
  const rt = ctx.response.get("X-Response-Time");
  console.log(`${ctx.method} ${ctx.url} - ${rt}`);
});

app.use(async (ctx, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  ctx.set("X-Response-Time", `${ms}ms`);
});

router.get("/search/:breed", async (ctx, next) => {
  const { breed } = ctx.params;
  const { message } = await fetchBreedImage(format(breed));
  ctx.body = message;
});

const fetchBreedImage = breed =>
  fetch(`https://dog.ceo/api/breed/${breed}/images`)
    .then((res) => res.json())
    .catch((err) => console.log({ err }));

app.use(serve("./static"));

app.use(router.routes());

app.listen(port, () => {
  console.log(`Server running on http://localhost:${port}`);
});

Try this:


URL: https://codesandbox.io/s/sharp-galois-nq9zf9

Remarks:


If this answer was not satisfactory, or confusing, or did not answer what was asked, please comment so I can edit it.

It's worth mentioning that I'm using google translator to answer, I apologize for any inconvenience
Lucas Paixão
  • 862
  • 5
  • 11
  • 1
    Yes, that's perfect. Thank you so much. I think I should be okay now. That was extremely helpful I think I can figure out how the rest. If not, I can always create a new issue because this one helped me quickly get unstuck. Thank you – Brendan F Oct 16 '22 at 00:57
  • 1
    That passing of the params in Koa is exactly what I was trying to figure out. I knew I was close because in express I could just do whatever = req.params and in the url it be whatever/:searchTerm but that answer was perfect. I guess that ctx or ctx confused me. Thanks. – Brendan F Oct 16 '22 at 01:02
  • @BrendanF Please mark the answer as accepted, but anyway I'm glad I was able to help you :), any questions feel free to ask that we are here to help each other. – Lucas Paixão Oct 16 '22 at 01:07
  • Please [do not just post some links to elsewhere](https://meta.stackexchange.com/q/8231), but rather a self-contained answer to the question. – Bergi Oct 16 '22 at 03:39
  • @Bergi Please check if it is now in accordance with the recommended, thank you in advance, Lucas P. – Lucas Paixão Oct 16 '22 at 16:33
  • @LucasPaixão Thanks, that's perfect - explanation of the problem, explanation of the solution, full code of the solution - and a runnable codesandbox on top, but it doesn't matter if that link breaks at some point. – Bergi Oct 16 '22 at 16:48
  • Hi, so on the form on the front end, how would I send that search term to the backend? I have been trying to use axios.post(`localhost:3011/search/${searchTerm}`) on a handleChange function. I can't seem to get that param to the backend correctly, but I understand from my original question how to get things done once the searchTerm is recieved in the back. – Brendan F Oct 18 '22 at 20:06
0

Thank you Lucas Paixao for the answer. I have multiple days left until this assessments due and this put me ahead. I got an answer within 2 hours of posting and I have one week to complete it. The answer I wanted was how to pass the params from front to back. I'd used express but not koa, same founders. I guess ctx confused me. express I could just put req.params but in koa it would be ctx.params.

The answer I received....

import Koa from "koa";
import Router from "@koa/router";
import cors from "@koa/cors";
import fetch from "isomorphic-fetch";
import serve from "koa-static";

const app = new Koa();
const router = new Router();
const port = 8000;

const format = str =>
  str.toLowerCase()
     .replace(/\s/g, '');

app.use(cors({ origin: "*" }));

router.get("/", (ctx) => {
  ctx.body = "hello!";
});

app.use(async (ctx, next) => {
  await next();
  const rt = ctx.response.get("X-Response-Time");
  console.log(`${ctx.method} ${ctx.url} - ${rt}`);
});

app.use(async (ctx, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  ctx.set("X-Response-Time", `${ms}ms`);
});

router.get("/search/:breed", async (ctx, next) => {
  const { breed } = ctx.params;
  const { message } = await fetchBreedImage(format(breed));
  ctx.body = message;
});

const fetchBreedImage = breed =>
  fetch(`https://dog.ceo/api/breed/${breed}/images`)
    .then((res) => res.json())
    .catch((err) => console.log({ err }));

app.use(serve("./static"));

app.use(router.routes());

app.listen(port, () => {
  console.log(`Server running on http://localhost:${port}`);
});
Brendan F
  • 19
  • 1