#Client side data fetching, data gets mixed up between different calls

20 messages · Page 1 of 1 (latest)

knotty solar
#

I am having an issue with loading data. Just in general, I have a feeling there’s little logic (or clarity) in how the data gets loaded. I will explain the issues I’m running into and I hope someone can help me out.

I have a website where people fill out a questionnaire and after doing so end up on a results page. To get the the results page, we assign a cookie/hex code to them and we retrieve all their info based off that. I’m trying to load their Strengths and Risks. I first tried to load these server side using a plugin that checks if it needs to get populated (*.server.ts and $fetch), but I ran into some issues there and figured I don’t need the SEO benefits on that page anyway, so I’ll render it just on the client side. I renamed my component to Card.client.vue and this is where things got weird.

I have some load functions for the data that assign the data to refs. 

```
const userRisks = ref<IUserRisk[]>([]);
const allStrengths = ref<IUserStrength[]>([]);

const loadStrengths = async () => {
const strengths = await useStrengths(userId);
allStrengths.value = strengths.value;
};
const loadRisks = async () => {
const strengths = await useRisks(userId);
userRisks.value = strengths.value;
};

loadStrengths();
loadRisks();


The problem I’m running into is that after the client side renders, the strengths are stored (duplicated?) into the risks variable. And the risks are not there, even though I see the risks being loaded through when I log them in the hooks. The weirdest part is that when I log the strength data, after getting it from the API, in the useStrenghts hook (see below), it logs risks. _But checking the network tab in the browser shows that there are two API calls, one to strengths and one to risks and both return the expected data_. I’ve been staring at this problem for too long and I sincerely hope someone has an idea about all this 😅
#

The hooks are very simple, they just do an api query via a wrapped useFetch.

// useStrengths.ts
export default async function useStrengths(
  sessionCookie: string
): Promise<Ref<IUserStrength[]>> {
  const strengths = await useApi<IUserStrength[]>(
    () => `/user/${sessionCookie}/strengths`
  );
  console.log(‘strengths.data’, strengths.data) // This logs risks ??
  return strengths.data as Ref<IUserStrength[]>;
}

// useRisks.ts
import { IUserRisk } from '~/types/apiResponse/userRisk';

export default async function useRisks(
  sessionCookie: string
): Promise<Ref<IUserRisk[]>> {
  const risks = await useApi<IUserRisk[]>(() => `/user/${sessionCookie}/risks`);
  console.log(‘risks.data’, risks.data) // This also logs risks ??
  return risks.data as Ref<IUserRisk[]>;
}

// useApi.ts
import { UseFetchOptions } from '#app';
import { RouterMethod } from 'h3';
import { NitroFetchRequest } from 'nitropack';
import { FetchError, FetchOptions } from 'ofetch';

export function useApi<T>(
  url: string | (() => string),
  options: UseFetchOptions<T> = {}
) {
  options.$fetch = $fetchCreate();

  return useFetch<T, FetchError, NitroFetchRequest, RouterMethod, T>(
    url,
    options
  );
}

function $fetchCreate() {
  const options: FetchOptions = {};

  const config = useRuntimeConfig();

  options.baseURL = config.public.API_URL;
  options.headers = {
    ...options.headers,
    Accept: 'application/json',
  };

  return $fetch.create(options);
}

I would be super grateful if there would be someone who can point out to me what I am doing wrong and/or point me to some good reading material for Nuxt data loading and how to set up serverside vs clientside. I have a bunch of NextJS experience, but I cannot seem to get a grip on the way Nuxt does it somehow. Any help is much appreciated.

gray jasper
#

If you swap the calls round does the issue happen the other way around? For example fetching strengths before risks and vice versa?

#

It could be that Nuxt is generating identical keys for each request

#

Try setting key explicitly, ensure its different for each request path

#

Do you have a repoduction for this?

gray jasper
#

This is a Nuxt bug, because you're using () => "" to define paths Nuxt doesn't add this to the key, the autoKey is meant to help with this but this will be the same value for both as they share the "same" useFetch within useAPI

#

You set key explicitly to workaround, or explicitly define path

gray jasper
#

Bug fixed in latest commit

knotty solar
#

Hi @gray jasper Thanks for the replies! I was away this weekend, but yeah, it happens the other way around too. I'll try adding the key to it later today and will confirm that it works then 👌

knotty solar
#

Hi @gray jasper,

Can confirm, it works with a key. However, now I'm running into the following issue where the data seems not to load at first.
I'm trying to do something with the returned strengths in the loadStrengths function, but on initial inspection it is null.

  const strengths = await useStrengths(userId);
  allStrengths.value = strengths.value;
  console.log('strengths.value', strengths.value) // null
  // ... do stuff with strengths.value -> error 'cannot call x of null'
};```
gray jasper
#

How do you mean?

knotty solar
#

If I set a watcher on the allStrengths.value that triggers the things I want to do, it works, but it seems to be that there is some async/await step not happening

#

As if the fetch returns even though it should wait a little longer

#

@gray jasper If I reload the page, this is the problem, the initial load of the data shows value is null. Only afterwards it populates it. Which would mean I need to do a watcher to update the data. But that means I need to do all kinds of weird tricks to track it, because if strengths.value is null and that gets assigned to allStrengths.value, it won't see a change where strengths.value actually gets populated.

gray jasper
#

that is weird, are you keys different and you’ve not set anything like server:false ? Also what mode is this on?

knotty solar
#

Nope, nothing like that. I'm just running it pretty much out of the box. With mode you mean development or production? This is all local.

Hmm, I think it's related to this issue: https://stackoverflow.com/questions/74759799/nuxt-3-ssr-usefetch-returning-null-on-page-refresh).

If I wrap the calls in an await nextTick( async () => await useStrengths(userId)) it does work, although it still first tells me that Cannot read properties of null (reading 'length'), but subsequently the data does load in.

#

For versions:

nuxt 3.5.3
node 17.0.1

#

@gray jasper This is the setup I have now and it seems to work without throwing any errors:

<script setup>
// ... imports & refs ,,,

const loadStrengths = async () => {
  await nextTick(async () => {
    const strengths = await useStrengths(userId);
    allStrengths.value = strengths.value;

    if (strengths.value?.length) {
      // handle loaded strengths
    }
  });
};
const loadRisks = async () => {
  await nextTick(async () => {
    const risks = await useRisks(userId);
    userRisks.value = risks.value;
  });
};

loadStrengths();
loadRisks();
</script>
gray jasper
#

I’d open an issue on Girhub, definitely seems like another big