rich-text icon indicating copy to clipboard operation
rich-text copied to clipboard

GraphQL unresolved data-model

Open mrsteele opened this issue 6 years ago • 5 comments
trafficstars

I am having issues with rendering data from GraphQL into react since the links are unresolved...

When using this plugin with the contentful.js module it works great because everything is resolved in rich-text.

We tried to use the graphql api and everything is unresolved. I wrote a weird thing to manually resolve things myself, but I would love to see if you guys already have something that either does this for us (through this plugin, or another by Contentful).

Is there a way we can either resolve the linked content, or pass in the whole field from graphql to have the renderer resolve these?

Below is the logic route we took and the problem we face.

// get data from Contentful with GraphQL
const entry = await fetchWithGraphQL(`
query {
  articleCollection (limit: 1) {
    body {
      json
      links {
        entries {
          block {
            ... on CaptionBlock {
              __typename
              title
              sys {
                id
              }
              youGetTheIdea
            }
          }
        }
      }
    }
  }
}`)

// Render data. This is where I wonder if we need to resolve the graphql data ourselves first...
const Component = ({ entry }) => (
  <div>
    {documentToReactComponents(entry.body.json, contentfulRichTextOptons)}
  </div>
)

mrsteele avatar Nov 06 '19 21:11 mrsteele

Surprised no one answered this... If anyone else is wondering about this my solution was to wrap the documentToReactComponents call in my own function which passes body.links so we can reference it + find the linked entries through filtering:

const generateBody = (bodyJSON: Document, links: any) => {
	const options: Options = {
		renderNode: {
			[BLOCKS.EMBEDDED_ENTRY]: (node: any, children) => {
				// Have access to links here, filter then render appropriate component
				return <div>embedded</div>;
			},
		},
	};

	return documentToReactComponents(bodyJSON, options);
};

colton-savage-lmp avatar Aug 25 '20 13:08 colton-savage-lmp

@colton-savage-lmp I don't know why I didn't consider this initially. Thanks for sharing!

mrsteele avatar Aug 25 '20 14:08 mrsteele

@colton-savage-lmp about your solution, does that mean that you have to fetch your links data yourself in the renderNode method? Could you share a more detailed example? 🙏

pybuche avatar Nov 13 '20 09:11 pybuche

@pybuche Sure thing, basically the idea is to pull the entry ID from the node then you find the entry from the links you pass in to your function separately:

// inside generateBody
[BLOCKS.EMBEDDED_ENTRY]: (node: any) => {
	const linkFieldMap: { [index: string]: any } = {
		'embedded-entry-block': 'block',
	};
	const linkField = linkFieldMap[node.nodeType];
	const targetId = node.data?.target?.sys?.id;
	const entry = links.entries[linkField].filter(
		(cur: any) => cur.sys?.id === targetId
	)[0];

	if (!entry) {
		return null;
	}

	switch (entry.__typename) {
		case 'Quote':
			return <Quote entry={entry} />;
		default:
			return null;
	}
},
// Example generateBody call
generateBody(body?.json, body?.links)

colton-savage-lmp avatar Nov 13 '20 14:11 colton-savage-lmp

Surprised no one answered this... If anyone else is wondering about this my solution was to wrap the documentToReactComponents call in my own function which passes body.links so we can reference it + find the linked entries through filtering:

const generateBody = (bodyJSON: Document, links: any) => {
	const options: Options = {
		renderNode: {
			[BLOCKS.EMBEDDED_ENTRY]: (node: any, children) => {
				// Have access to links here, filter then render appropriate component
				return <div>embedded</div>;
			},
		},
	};

	return documentToReactComponents(bodyJSON, options);
};

I thought about doing this, but I figured there had to be a better way/something I was missing in the documentation. Apparently not. If the maintainers read this, please give us an easier way to use this library with GraphQL!

pjaws avatar Jan 27 '21 21:01 pjaws