Can you use Sanity Fetcher to fetch one post or rendering portable text?

Couple of questions related to dynamic pages and Sanity Fetcher:

  1. Is it possible to use the dynamic value (for example a blog post slug) in the Sanity Fetcher to fetch only one post?
  2. How would one go on about rendering Sanity’s portable text with Plasmic? We have multiple custom blocks in them as well

Hi @top_cat
You have the flexibility to design the Sanity Fetcher to behave however you want. The one you see in the Plasmic component store only exports two packages - The Sanity Fetcher - to fetch your Sanity Documents and the Sanity Field - to display the different fields on your Documents. You can however extend this functionality to suit your specific use cases here https://github.com/plasmicapp/plasmic/tree/master/plasmicpkgs/plasmic-sanity-io

And regarding the built-in behavior:

  1. It only fetches full collections, but like Kenny mentioned you can fork the package to add this to the code component
  2. Portable text is a low-level schema that doesn’t actually prescribe any formatting or rendering - it’s meant for code to interpret however they want, so you can author the rendering code components for your app, built on something like https://www.sanity.io/docs/portable-text-to-react

Thanks for the answers! :slightly_smiling_face: I’ll ask around if I need something more

Hey!

I started customizing the plasmic-sanity-io package to better suit my use case. I got everything working nicely with a lot of possibilities to customize the GROQ query and to also render portable text properly etc.

Although when I create a dynamic page in Plasmic, e.g. /blog/[slug] and configure that on my Next.js site, I get the following error when going to my newly created blog post page:

error - TypeError: Cannot read properties of undefined (reading 'name')
    at toFullLookup (/Users/.../plasmic-website/node_modules/@plasmicapp/loader-react/dist/loader-react.cjs.development.js:1091:63)
    at getCompMetas (/Users/.../plasmic-website/node_modules/@plasmicapp/loader-react/dist/loader-react.cjs.development.js:1184:14)
    at _loop (/Users/.../plasmic-website/node_modules/@plasmicapp/loader-react/dist/loader-react.cjs.development.js:2095:19)
    at InternalPlasmicComponentLoader.refreshRegistry (/Users/.../plasmic-website/node_modules/@plasmicapp/loader-react/dist/loader-react.cjs.development.js:2106:7)
    at InternalPlasmicComponentLoader.mergeBundle (/Users/.../plasmic-website/node_modules/@plasmicapp/loader-react/dist/loader-react.cjs.development.js:2087:10)
    at InternalPlasmicComponentLoader._callee8$ (/Users/.../plasmic-website/node_modules/@plasmicapp/loader-react/dist/loader-react.cjs.development.js:2064:20)
    at tryCatch (/Users/.../plasmic-website/node_modules/@plasmicapp/loader-react/dist/loader-react.cjs.development.js:373:19)
    at Generator.invoke [as _invoke] (/Users/.../plasmic-website/node_modules/@plasmicapp/loader-react/dist/loader-react.cjs.development.js:587:24)
    at Generator.next (/Users/.../plasmic-website/node_modules/@plasmicapp/loader-react/dist/loader-react.cjs.development.js:425:23)
    at asyncGeneratorStep (/Users/.../plasmic-website/node_modules/@plasmicapp/loader-react/dist/loader-react.cjs.development.js:23:24) {
  type: 'TypeError',
  page: '/[[...catchall]]'
}

I have narrowed the problem to the SanityFetcher component, and probably its registration. If I comment out the row where I register that component, the project hot-reloads and I can see my page (without the content obviously). If I uncomment the row, after hot-reload I see content and everything nicely. But if I refresh the page, I get the error again.

Something to with SSR/SSG? Any obvious places where I might have done something wrong? @burning_silkworm @yang

Also to note, I do not use the forked plasmic-sanity-io package as an NPM module but just copy-pasted the files (at least for now) and call the registerAll function in my plasmic-init.ts

Hi @top_cat, I’m having some trouble reproducing this issue - copying the sanity io package to my own test app host is working for me, but do you have an example repo demonstrating the issue you’re seeing? That can help me debug

Is it possible you are missing a name property on the registerComponent or substituteComponent call (that it’s undefined)?

Private repo, so can’t share it directly. Here’s my modified package. What I have changed is refactored components to different files, PortableText support for SanityField, and a query-builder that is used in SanityFetcher.

plasmic-sanity-io.zip

Managed to figure out something more. If I pass my PlasmicLoader to the registerAll function I get the error, but after a hot-reload happens on Next, everything works until a refresh. Although when I do not pass the loader to the function, there is no error. But on the other hand there is no actual content coming from Sanity then. This is how my plasmic-init.ts looks like:

import { initPlasmicLoader } from "@plasmicapp/loader-nextjs";

import { registerAll as registerAllSanityComponents } from "./components/plasmic-sanity-io";

const PLASMIC_PROJECT_ID = process.env.NEXT_PUBLIC_PLASMIC_PROJECT_ID;
const PLASMIC_PUBLIC_API_TOKEN =
  process.env.NEXT_PUBLIC_PLASMIC_PUBLIC_API_TOKEN;

if (!PLASMIC_PROJECT_ID || !PLASMIC_PUBLIC_API_TOKEN) {
  throw new Error(
    "PLASMIC_PROJECT_ID and PLASMIC_PUBLIC_API_TOKEN must be set in the environment"
  );
}

export const PLASMIC = initPlasmicLoader({
  projects: [
    {
      id: PLASMIC_PROJECT_ID,
      token: PLASMIC_PUBLIC_API_TOKEN,
    },
  ],

  // By default Plasmic will use the last published version of your project.
  // For development, you can set preview to true, which will use the unpublished
  // project, allowing you to see your designs without publishing.  Please
  // only use this for development, as this is significantly slower.
  preview: process.env.NODE_ENV === "development",
});

// Throws an error but after hot-reload gets data
registerAllSanityComponents(PLASMIC);

// No error but also no data
registerAllSanityComponents();

More findings:

This only occurs on development, not with a production build.

Debugged a bit of the development distribution of the loader.

In the toFullLookup function that causes the error I logged what the lookup looks like:

function toFullLookup(lookup) {
  console.log('**** toFullLookup', {lookup, typeof: typeof lookup})
  var namePart = typeof lookup === 'string' ? lookup : lookup.name;
  var projectId = typeof lookup === 'string' ? undefined : lookup.projectId;
  var codeComponent = typeof lookup === 'string' ? undefined : lookup.isCode;

  if (codeComponent !== true && namePart.startsWith('/')) {
    return {
      path: normalizePath(namePart),
      projectId: projectId
    };
  } else {
    return {
      name: codeComponent ? namePart : normalizeName(namePart),
      rawName: namePart.trim(),
      projectId: projectId,
      isCode: codeComponent
    };
  }
}

This is the result I get:

**** toFullLookup {
  lookup: { name: 'SanityCredentialsProvider', isCode: true },
  typeof: 'object'
}
**** toFullLookup { lookup: undefined, typeof: 'undefined' }

The CredentialsProvider works as expected, but the next one is the Fetcher and for some reason the whole lookup is undefined :thinking_face: any ideas?

In getCompMetas I get the following for SanityFetcher. The metadata is found correctly:

    {
      id: 'btk0ScIiDQ',
      displayName: 'SanityFetcher',
      usedComponents: [Array],
      projectId: 'cZU4ZZCeedmfBgrGsLHyHo',
      name: 'SanityFetcher',
      renderFile: 'render__btk0ScIiDQ.js',
      skeletonFile: 'comp__btk0ScIiDQ.js',
      cssFile: 'css__btk0ScIiDQ.css',
      isPage: false,
      entry: 'comp__btk0ScIiDQ.js',
      isCode: true,
      isGlobalContextProvider: false,
      metadata: {}
    },

But the lookup here is undefined

SOLVED!

It had nothing to do with Plasmic. The problem was with my imports and exports, especially with the export * notation. VS Code resolved everything correctly but for some reason somewhere with Next/Plasmic, the SanityFetcher imports were undefined. Solved by using more verbose imports.

Thanks a lot for your help! :slightly_smiling_face: Or being my rubber duck :duck: :laughing:

Whew!

Nice debugging, pretty tricky…

Hey :wave: forgive me for the noob Plasmic Q’s. I’ve figured out how to integrate Sanity with the REST API and I’ve got data populating, but I don’t know how to use the portableText features. Anyone figured this out?

Usually with portable text, since you are essentially inventing your own text format, you’ll need your own code components that know how to render that format into what you ultimately want to show on screen