0

I have a component in SolidJS, an Artist page. It looks as follows:

export function Artist() {
  const params = useParams<{ id: string }>();
  const [data, setData] = createSignal(null);
  createEffect(() => {
    fetchArtist({
      devToken: import.meta.env.VITE_MUSICKIT_TOKEN,
      musicUserToken: MusicKit.getInstance()?.musicUserToken,
      id: params.id,
    }).then((res) => setData(res));
  });

  return (
    <div class={styles.artist}>
      <Show when={data()}>
        <div class={styles.artist__header}>
          <div class={styles.artist__header__image}>
            <img
              loading="lazy"
              decoding="async"
              src={replaceSrc(
                data()?.data[0].attributes?.editorialArtwork?.subscriptionHero
                  ?.url || data()?.data[0].attributes?.artwork?.url,
                data()?.data[0].attributes?.editorialArtwork?.subscriptionHero
                  ?.height || data()?.data[0].attributes?.artwork?.height,
              )}
              alt="Album Art"
              width={100}
              height={100}
              class={styles.artist__header__image__img}
            />
          </div>
          <div class={styles.artist__header__info}>
            <div class={styles.artist__header__info__title}>
              {data()?.data[0].attributes?.name}
            </div>
            <div class={styles.artist__header__info__subtitle}>
              {data()?.data[0].attributes?.genreNames?.[0]}
            </div>
            <div class={styles.artist__header__info__actions}>
              <ButtonPrimary
                label="Play"
                icon={IoPlay}
                onClick={() => {
                  setIsShuffle({ value: 0 });
                  setQueue("artist", data()?.data[0].id, true);
                }}
              />
            </div>
          </div>
        </div>
        <div class={styles.artist__body}>
          <ArtistViewSelector artist={data} data={data} />
        </div>
      </Show>
    </div>
  );
}

My issue is, the ArtistViewSelector component is not updating when the fetch data is changed. This happens, for instance, when I click on a different artist on the same page.

Only the code not contained within the ArtistViewSelector (e.g. the artist image) seems to be updating. I am not sure why this is.

Scarlet
  • 1
  • 2

1 Answers1

0

There is no way to know without knowing the implementation of ArtistViewSelector however there are several issues with your component.

First and foremost you should not use an effect to update a state, because it will put your component into an infinite loop.

If you think through, you will see you don't need to put fetchArtist into an effect but place directly inside the component body, fetch request will be sent because components are wrapped in effects internally.

Another issue is lack of error handling. There is no guarantee that all fetch request resolve to a value without failing. So, you need to consider adding error handling.

There are other issues but I will keep it short.

Now, what you should do is use a resource for fetching and rendering data. Resource API allows you to send fetch request with query parameters, handle re-fetches and errors with a clean and concise code.

You can do it using fetch API too. Please check this answer for how to do it with and without resource API: https://stackoverflow.com/a/74590574/7134134

Resource API: https://www.solidjs.com/docs/latest#createresource

snnsnn
  • 10,486
  • 4
  • 39
  • 44
  • Thank you, I will look into the resource API. If you don't mind, what are the other issues? – Scarlet Jul 26 '23 at 12:32
  • No loading indicator, no error handling, not that important but no re-fetching mechanism, onclick may trigger multiple re-renders due to consecutive state update, it should be batched. This component produces very large bundle because there is no way to minify property access. Components provide us more than code re-use. You should aim for both performance and smaller bundle size. – snnsnn Jul 26 '23 at 14:34