previewSrc on an image block (in settings field) with GitHub Open Auth

I have an image block and I want folks to be able to edit that via the settings modal. The issue is that I need to provide the proper github url when new images are uploaded. Here is how I would like to have it work:

From the fields array in the block template

previewSrc: (formValues, input) => {
  const cms = useCMS()
  const currentBlockImage =
    formValues.index_blocks[getBlockIndex(input.field)].src
  const workingRepository = cms.api.github.workingRepoFullName
  const currentBranch = cms.api.github.branchName
  return `https:raw.githubusercontent.com/${workingRepository}/${currentBranch}/public${currentBlockImage}`
},

Obivously in the block component this works fine, but in the template I get the ‘cannot call a hook outside of a function component’ error with useCMS. I need a way to access information about the github api config without using this hook. Any ideas?

Are you defining the block template inside of a function component? If so, you could call useCMS() in the function component scope and it will be inherited in the arrow function.

Ultimately, since the CMS object is passed around via context, configuration will always need to originate from a react component that can pull it out of context. If the above solution doesn’t work here, could you provide a more complete code example to demonstrate the problem?

Yeah that’s the issue, the template isn’t defined in the function so I can’t use that useCMS hook. Here’s the source file. The code above is commented out cause that hook call throws an error. But you can see the general gist.

One thing you could do is, instead of exporting the image_template object, export a createImageTemplate function that accepts the CMS object so you can use it in previewSrc.

export function createImageTemplateConfig(cms: TinaCMS) {
  return {
    type: 'image',
    label: 'Image',
    previewSrc: (formValues, input) => {
        const workingRepository = cms.api.github.workingRepoFullName
        //...
    }
  }
}

I don’t love this solution, but like I said, in order to pull the CMS out of context, we need to be in a component scope. This can at least help a bit with code organization, so you don’t have to inline all of this config inside of the component.

A better solution might be to pass the CMS object into the previewSrc function if we can. We should probably try to pass it in to any field callback, as we should assume that registered APIs may need to be called at any time.

Side note: your previewSrc example won’t work with private repos. I’m working on some updates to GithubClient that will include a getMediaUri function, which will also simplify your implementation. While you could get the repo name and branch name directly from the cookies they’re stored in, bypassing the need to call the API, I don’t recommend that and it would be better if we just made it easier to grab the CMS object in these callbacks.

Nice, thats a good idea. This is how it turned out… in the index blocks definition, and then for the image template.

I think you’re right though we should probably pass the cms into previewSrc. I’ll look into that / make an issue. And that’s awesome that you’re working on some updates to make accessing those values easier! Stoked to see it.

1 Like