Retrieve slice content from relationship inside another slice

I've got a page set up on my Gatsby site that displays different product styles in a slice. What I need, however, is to allow content editors to show those product styles on the homepage, using a content relationship field. I've got it set up and working generally correctly, however I think that there might be a better way to do it, as right now I'm mapping over the data from the product page and pulling it into the slice on my homepage, but, since I'm only every querying the one slice from the product page, I don't know as though I need a map. Is there a more efficient way to pull this content into my homepage?

export const ProductStyles = ({ slice }: any) => {
  const document = slice.primary.products;
  if (!document) return null;

  const headingRef = useRef(null);
  const copyRef = useRef(null);

  const animate = () => {
    const t = new TimelineLite();

    t.fromTo(headingRef.current, { y: 65 }, { y: 0, duration: 1, clearProps: 'transform' }).fromTo(
      copyRef.current,
      { autoAlpha: 0, y: 20 },
      { autoAlpha: 1, y: 0, duration: 1, clearProps: 'visibility, transform' },
    );
  };

  const documentContent = document.body
    ? document.body.map((content: any, index: number) => {
        if (content.type === 'styles') {
          return (
            <ViewportEnter onEnter={animate} margin="0% 0%">
              <div className={s.grid} key={`${index}`}>
                <div className={s.grid__container}>
                  <div className={s.top}>
                    <HeadingReveal tag="h2" forwardRef={headingRef}>
                      {RichText.asText(content.primary.heading)}
                    </HeadingReveal>
                    <div className={s.top__copy} ref={copyRef}>
                      {RichText.render(content.primary.copy, linkResolver, htmlSerializer)}
                    </div>
                  </div>
                  <Row>
                    {content.fields.map((product: any, i: number) => (
                      <div
                        className={css(s.item, product.product_category.toLowerCase())}
                        key={`${i}`}
                      >
                        <div className={s.item__image}>
                          <img src={product.image.url} alt={product.image.alt} />
                        </div>
                        <div className={s.item__info}>
                          <strong className={s.item__name}>{product.product_name}</strong>
                          <h4 className={s.item__category}>{product.product_category}</h4>
                        </div>
                      </div>
                    ))}
                  </Row>
                </div>
              </div>
            </ViewportEnter>
          );
        }
        return null;
      })
    : null;

  return <div className={s.products}>{documentContent}</div>;
};

Hi @jesse. There's nothing wrong with the way you have this setup, it should work just fine.

If you're only looking for one slice type, then I might first pass the Slice Zone through a filter to give you an array of only 'styles' slices. Then map over that. I don't really know if that optimizes the code much or at all, though.

The other option is if you only need one instance of the 'styles' slice type. If that's the case, then you can you can use the find method to get the first instance of that type. Then you can return the jsx using that.

But as I mentioned above, what you have here would work great for what you need, so it's up to you :grinning:

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.