Get block count from outside InlineBlocks

I have a component that looks like this:

export function Gallery({ index }) {
  return (
    <section id="gallery">
      <h2>
        <InlineText name="title" />
      </h2>
      <BlocksControls index={index}>
        <InlineBlocks name="galleryItems" blocks={GALLERY_BLOCKS} />
      </BlocksControls>
      <!-- I'd like an extra element rendered here, but -->
      <!-- only when there are more than 6 gallery items -->
    </section>
  )
}

I can see in the source code at tinacms/inline-field-blocks.tsx at master · tinacms/tinacms · GitHub that InlineBlocksActions has a count attribute, which is what I’d like to read. But I don’t know how I can access that count, from my component that renders the InlineBlocks.

Help with this would be much appreciated.

@logan Any idea how to use count for inline blocks?

Hello @jaza and thanks for your question! Just as a reminder the inline editing libraries are considered experimental and are likely to change. For more context see our blog post.

Saying that, you should be able to get the desired outcome by doing this.

export function Gallery({ index }) {
  const blocks = useInlineBlocks()
  return (
    <section id="gallery">
      <h2>
        <InlineText name="title" />
      </h2>
      <BlocksControls index={index}>
        <InlineBlocks name="galleryItems" blocks={GALLERY_BLOCKS} />
      </BlocksControls>
      <!-- I'd like an extra element rendered here, but -->
      <!-- only when there are more than 6 gallery items -->
      {blocks.count > 6 && <Something />}
    </section>
  )
}

Thanks again for your question and let us know if there is anything else we can help you with.

2 Likes

@logan thanks for the answer, however, I already tried that myself (after posting this question), and it doesn’t work for me.

Sorry, I forgot to mention before, I’m using nested inline blocks. So the Gallery is itself an inline block (of which there’s only one instance on the page), and it in turn contains GalleryItem inline blocks.

When I add this, at the spot just after the BlocksControls where I want conditional rendering to happen:

<div>there are {blocks.count} blocks!</div>

It renders: “there are 1 blocks!” Whereas there are actually 13 gallery items on the page. I guess this is because it’s getting the context of the parent InlineBlocks, not the context of the child one.

I submitted a PR that solves this for me: feat(react-tinacms-inline): InlineBlocks children by Jaza · Pull Request #1852 · tinacms/tinacms · GitHub . The README text that I added explains the approach that I took:

Context and inline blocks children

To conditionally render markup adjacent to your inline blocks, depending on context values, pass children to the InlineBlocks and call useInlineBlocks in your child component(s). For example, this will render some text below your inline blocks, but only if there are more than three inline blocks currently on the page:

import { InlineBlocks, useInlineBlocks } from 'react-tinacms-inline'

export function LotsOfBlocksMessage() {
  const blocks = useInlineBlocks()
  return <>
    {blocks.count > 3 &&
      <p>
        Wow, there are {blocks.count} blocks, that's rather a lot!
      </p>
    }
  </>
}

export function MyBlocksContainer() {
  return (
    <InlineBlocks name="myBlocks" blocks={MY_BLOCKS}>
      <LotsOfBlocksMessage />
    </InlineBlocks>
  )
}

Just wanted to give an update here: the PR that I posted above has been merged, so it should now be possible to do what I was trying to do here, with the latest version of tinacms, without any hackery involved.

PS: I finished building my first Tina site (for which I asked this question in the first place), and I blogged about my experience, if anyone is interested: On Tina | GreenAsh

1 Like

Thank you for the feedback, much appreciated. :pray: