#List to detail page - fetching detail content

44 messages ยท Page 1 of 1 (latest)

shadow pivot
#

I've been struggling a few days with getting a test details page working from a list page. Coming from Vue so am bending my head around new things.
Here is the details page code which is on the route (2 as a sample id): http://localhost:5173/users/2/

import { component$ } from '@builder.io/qwik';
import { routeLoader$ } from '@builder.io/qwik-city';
import type { DocumentHead } from '@builder.io/qwik-city';

export const useUserLoader = routeLoader$(async ({ params }) => {
    const id = params.id;
    const response  = await fetch(`https://jsonplaceholder.typicode.com/users/${id})`);
    const user = await response.json();
    return user;
});

export default component$(() => {
  const user = useUserLoader();
  return (
        <div>
            {(user.value && user.value)} detail here
        </div>
      )
});
export const head: DocumentHead = {
  title: 'Welcome to Qwik',
  meta: [
    {
      name: 'description',
      content: 'Qwik site description',
    },
  ],
};

The error is:
One of the children of <div> is not an accepted value. JSX children must be either: string, boolean, number, <element>, Array, undefined/null, or a Promise/Signal. Instead, it's an instance of "SignalDerived".

The list page works fine calling the same API, so I'm confused as to where I'm going wrong. (attachment)

grave pumice
#

can you make a stackblitz or share the repo?

shadow pivot
#

sure - doing that now thanks

viscid rover
shadow pivot
#

Yes that works

#

I threw together a link on the listing page here in the test repo -
https://github.com/wedwardbeck/qwiktest

Click on "Test Page" top right then after list renders, any of the "Test detail " links on the right (hardcoded to id = 2)

GitHub

Contribute to wedwardbeck/qwiktest development by creating an account on GitHub.

viscid rover
#

Awesome!

Even though I was heavily in React before, and now constantly using Qwik, and overall love JSX, I reallllllly don't like the awkwardness of having to use ternaries and weird && expressions to do simple conditional rendering.

I made a super super super simple lil component to make that just feel nicer. Feel free to use it if it makes sense:

import { JSXNode } from "@builder.io/qwik";

export const If = (props: {
    isTrue: boolean | (() => boolean),
    show: JSXNode,
    elseShow?: JSXNode
}): JSXNode => {
    const isTrue = typeof props.isTrue === "boolean" ? props.isTrue : props.isTrue();
    return isTrue ? props.show : (props.elseShow || <></>)
};

Then you can import that and in your case it'd look like

import { component$ } from '@builder.io/qwik';
import { routeLoader$ } from '@builder.io/qwik-city';
import { If } from "../somewhere-you-choose.tsx"
import type { DocumentHead } from '@builder.io/qwik-city';

export const useUserLoader = routeLoader$(async ({ params }) => {
    const id = params.id;
    const response  = await fetch(`https://jsonplaceholder.typicode.com/users/${id})`);
    const user = await response.json();
    return user;
});

export default component$(() => {
  const user = useUserLoader();
  return (
        <div>
            <If isTrue={Boolean(user.value)} show={<p>Hi, felix!</p>} />
        </div>
      )
});
export const head: DocumentHead = {
  title: 'Welcome to Qwik',
  meta: [
    {
      name: 'description',
      content: 'Qwik site description',
    },
  ],
};
shadow pivot
#

Thanks will give this a try. Was this in one of your videos? They helped me get a few things cleared up quickly - thanks for those too.

viscid rover
#

oh wow glad to hear that! Thanks ๐Ÿ™‚ and nope, this one is pretty recent actually, haven't done any video about it

shadow pivot
#

If I replace the "Hi felix!" with user.value.name nothing shows. Based on your if - it is seeing a value in user.value because it shows the text - right? But when trying to output the user.value.name it is blank.

#

looks like I'm getting an empty object

#

maybe my URL is bad the way it gets parsed?

viscid rover
#

Interesting! -- oh that explains it

#

Yeah it's truthy just no data

shadow pivot
#

yes

viscid rover
#

oh! Ok just to get a feel for it, if you did isTrue={Boolean(user.value?.name)} then it'd save you from that

shadow pivot
#

I see it's encoding the text teh way I have it

viscid rover
#

and it makes sense from the app's perspective too - if that's the value you need to properly display your rendered component, then checking it for truthiness makes even more sense

#

oh nice! I got it now too:

{
  "id": 2,
  "name": "Ervin Howell",
  "username": "Antonette",
  "email": "[email protected]",
  "address": {
    "street": "Victor Plains",
    "suite": "Suite 879",
    "city": "Wisokyburgh",
    "zipcode": "90566-7771",
    "geo": {
      "lat": "-43.9509",
      "lng": "-34.4618"
    }
  },
  "phone": "010-692-6593 x09125",
  "website": "anastasia.net",
  "company": {
    "name": "Deckow-Crist",
    "catchPhrase": "Proactive didactic contingency",
    "bs": "synergize scalable supply-chains"
  }
}
shadow pivot
#

I've been fighting with appending a parameter to the url, but following other examples and repos I came to this:
fetch(`https://jsonplaceholder.typicode.com/users/~/~/${id})`);

viscid rover
shadow pivot
#

maybe there's a better way to do that - I'm trying to follow the patterns I used in Nuxt - which may be hindering me some

grave pumice
#

do you handle also if elseif else with such util component @viscid rover ?

viscid rover
viscid rover
shadow pivot
viscid rover
#

Nesting can be kinda ugly but if the alternative is just nesting a bunch of ternaries anyway it's already gonna be bad. This would be much better LUL

shadow pivot
#

Is there a better way to concat the href string with the {id}?

viscid rover
# shadow pivot I logged the params.id and it's showing 2 from the route - so the value is there

Ohhhhhhhh Okay yeah that makes sense my bad. In the opposite direction though I've found it so nice to just use the native URL object.

So

export const useUserLoader = routeLoader$(async ({ params }) => {
    const id = params.id;
    const endpoint = new URL(`https://jsonplaceholder.typicode.com/users/${id})`);
    const response  = await fetch(endpoint);
    const user = await response.json();
    return user;
});
shadow pivot
#

thanks let me try that

viscid rover
#

wait

#

something else is up here haha

#

https://jsonplaceholder.typicode.com/users/${id}) should easily turn bad into an ID no question, the string there has '2' in it in your case.

The $%7Bid%7D is literally '${id}' being sent, and then consequently getting URI encoded

#

ahh discord thinks the backticks are formatting but imagine the ` around the url

shadow pivot
#

yes - that's what I can't figure out why it's not passing the 2

viscid rover
#

That's perplexing LUL But you can probably work around it with something like

export const useUserLoader = routeLoader$(async ({ params }) => {
    const id = params.id;
    const endpoint = new URL("https://jsonplaceholder.typicode.com/users/");
    endpoint.pathname += id;
    const response  = await fetch(endpoint.toString());
    const user = await response.json();
    return user;
});
shadow pivot
#

That works but I just did endpoint.toString() on const endpoint = new URL(https://jsonplaceholder.typicode.com/users/${id});

viscid rover
#

ahhhh that might just be it! nice

shadow pivot
#

beautiful - thanks very much for the help! I have not seen others using toString like this, but I think the examples were using strings to begin with ({slug})

#
    const id = params.id;
  console.log(id);
    const endpoint = new URL(`https://jsonplaceholder.typicode.com/users/${id}`);
  console.log(endpoint.toString());
  const response  = await fetch(endpoint.toString());
  const user = await response.json();
  console.log(user);
    return user;
});```