-
Notifications
You must be signed in to change notification settings - Fork 110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gatsby-transformer-contentful-richtext use with React? #46
Comments
Hey @sarahbethfederman, Cheers, |
Is there any documentation on how to do this with gatsby? I don't know how to query for a rich text field in graphql without the plugin because it seems you have to specify all the fields and nesting |
OK so I figured out how to get the string:
and then use that with a custom renderer like so:
My questions are now:
|
Ok update! I figured this out. It seems to be working.
only remaining question is what is the best what to grab the entry from the ID |
hey @sarahbethfederman usually when you use the SDK to grab the content the entry should be resolved automatically for you. So you will have access to entry.fields |
I'm using the Gatsby-source-contentful plugin and it doesn't seem to. Any
workarounds?
…On Sat, Dec 15, 2018, 1:25 PM Khaled Garbaya ***@***.***> wrote:
hey @sarahbethfederman <https://github.com/sarahbethfederman> usually
when you use the SDK to grab the content the entry should be resolved
automatically for you. So you will have access to entry.fields
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#46 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AFaQmsu_6qcYszuGLpRKFOvV0rSPkhrTks5u5Wi3gaJpZM4ZSXCe>
.
|
hey @sarahbethfederman the gatsby-source-contentful is using the SDK under the hood, so it should resolve the entries for you |
It doesn't seem to, all I see is the id. How do I check and are there any workarounds? |
@sarahbethfederman Thanks for putting together that documentToJSX method :) Hopefully it'll become a part of the plugin. Although I'm not sure how you should override it from I'm not sure if my approach to converting regular internal hyperlinks into Gatsby Links is much different from the entry kinds you're trying to get working, but maybe it'll be of help to you? I'm parsing the html string into JSX presently rather than using your documentToJSX method(not sure how to get it working with the Link component due to the require/import issue). The logic to convert an anchor tag to a Link component is taken from the Gatsby docs here. |
Oh interesting solution! I'll have to check that out. I'm not using the configuration in The other issue I ran into was because my function returns an array of JSX, I get the each array item must have a unique key warning and haven't figured out a way to add that in, so it's just annoying atm. The internal links method is probably a better solution than what I was doing which was just using Anyway, would definitely be good to have this built in to the plugin! I stripped out all the typescript defs from the original documentToHTML function because we aren't using typescript so it'd need a little work, but happy to try to PR when I have a bit of time (or you're welcome to). |
I think it does work only on the initial sync, when deleting the |
Yikes. That's a pretty massive bug. Do you have any workarounds? |
I'm guessing it's due to not having information like when the entity/data was last modified? It's also why I can't ensure that my local/offline support is correct with what's on Contentful. There's also a similar problem I ran into early into my Contentful use with Gatsby, the Perhaps that's the same issue with RichText and and these embedded links? (though I'm confused why they work initially the first time but that data isn't kept afterwards instead of just not able to update like my ContentType with unpublished linked assets experience). I can't actually recall if deleting the cache fixed it or if I had to make some change on Contentful to the ContentType and undo it after to force a changed state(I think this resolved it). I know that with my case, GraphQL schema ignores the fields if none of the results have any data(eg all would return null) which gave added confusion as I knew the field existed on my ContentType. Does @Khaledgarbaya work at Contentful? If it's a bug on Contentful's end where we can do nothing about it, is avoiding a workaround possible with an actual fix? Surely these would be bugs that can affect Contentful users on paid plans too? |
It is not a bug, as I mentioned the sync API is intended to only return the changed entities so if you don't change a reference it won't be included there and the SDK can't resolve the link unless it does an extra HTTP call which we decided to not do.
It can be yes.
😂 Yes I do. |
I am very unclear how resolved entries disappearing is not a bug. Even if it is technically expected on your end, it's entirely unexpected behavior to your users. It makes it unusable to have unresolved entries. Again, is there a workaround you suggest? Do I have to abandon the plugin? Between the lack of react support and entries being unresolved, this plugin is proving to be very frustrating for seemingly basic use cases. Do you plan on fixing these issues or have a timeline in place? Is there an official support channel I can use? I'm on a deadline here and my org is a paying customer. @polarathene is the entries being unresolved an issue with your method as well? |
Deleting the cache should do the trick from what I understand, then the plugin has nothing to compare to and will pull the data down again fresh.
I don't think it can offer React support in terms of overrides like it does for the HTML strings, unless you go with JSX strings like I did via the JSX parser on component/client side(instead of node). That's due to the conflicting approaches for importing modules afaik. I've been asked about contributing the JSX parser approach which is more of a workaround, you have to write the overrides as JSX wrapped in a string(potentially error prone) and you must also provide the RichText component with the components you intend to use with it(so all possible components you expect could be in the string content). It does work though and no problems so far.
As a paying customer it'd probably help raise priority for it :) Though if the JSX parser solution works for you, I could possibly have that contributed within the week(+however long it takes to get reviewed/merged), few other tasks to take care of first.
Umm I don't have anything too fancy in my RichText content, just web and internal links. I could try reproduce something similar to what you're having trouble with and see though? My similar bug was unrelated to RichText, I had a ContentType with a field that links to ContentfulAssets(images) that I published without publishing the images. That resulted in the field for them being null and omitted in the GraphQL schema. Forcing an update on my ContentType entry via Contentful in the browser fixed that and I could query the field to get ContentfulAssets again. |
The internal links you have are resolving properly? Deleting the cache folder brings up this issue for me so that doesn't help unfortunately. #53 |
Well they are just text for me, a hyperlink to nothing related to Contentful, but a different url like mydomain.com/contact, mydomain.com/services.. except to make them internal gatsby links I would have /contact and /services instead. When I've finished up some other todo items, I'll try out some internal Contentful links? Do you have any examples of what you're linking to? Just another ContentType or an Image asset? |
So it looks like contentful only sends the link text for entry_hyperlinks from the API response. https://www.contentful.com/developers/docs/concepts/rich-text/ I don't understand how I'm supposed to link to something with just the link text. There's no way to access the slug unless I do a full embedded entry. I tried using the sys.id that's returned to manually get the entry from the SDK but the id doesn't refer to an existing contentful entry, so I'm not sure what the id is supposed to refer to. I'm going to have to convert every entry-hyperlink to an inline entry just to get the slug I guess. |
Where is the sadface emoji reaction? :( @Khaledgarbaya if this is not something we can contribute a fix for, can you chime in ith Contentful's stance/plans on this? I understand it's still a beta component and GraphQL is in beta too(though I think Gatsby's GraphQL is separate from that, haven't looked much into how the data is being queried from Contentful. |
Hey @sarahbethfederman,
if you take a closer look at the payload there is data: {
target: {
sys: {
id: "7GI6AkMKWIqiiUIuG0uAO",
type: "Link",
linkType: "Entry"
}
}
} that's the mbedded entry and the SDK be able to resolve the link, it will append |
Oh yes I see, it just wasn't resolving. Are there plans to fix this so contentful can be used with |
Current working code if anyone else is working on this: https://gist.github.com/sarahbethfederman/04613d376188f71a1995228f33c38328 |
It looks like nested embedded entries (embedded entries that include an embedded entry) are not resolved, is this being worked on by chance? |
@sarahbethfederman I'm not working on anything related to this presently, still chugging away on other tasks. Looking forward to a response from @Khaledgarbaya about Contentful's stance on how it should be handled(assuming it matters to them to allocate paid hours to it, and/or an issue on their end that we're not able to resolve). He has not really responded about my queries specific to the company's involvement(and may not be able to? Blink twice if you're in danger! :o ). I haven't looked into using Contentful as much as you are, perhaps you can setup a repo that reproduces the problem? Gatsby repo has a using-contentful example project that has some public secrets iirc, adding a rich-text example there might be a good idea? |
Based on this issue gatsbyjs/gatsby#10592
is not an issue |
I have also been looking into this for a project and commented on the separate issue #54 around this. One of my first contributions to any project so hopefully I am approaching all of this properly. I think the current working version makes assumptions that the developer is returning a React element in their callbacks and not just a text node or null. The following should resolve it and feels a lot less hacky since it just uses React helpers. I also does not attempt to overwrite user input keys which might be desirable for something like preserving state by using an embedded assets id as a key: import React, {isValidElement, cloneElement} from 'react';
const appendKeyToValidElement = (element, key) => {
if (element && isValidElement(element) && element.key === null) {
return cloneElement(element, {key});
}
return element;
}; Full working version in the links below: |
@mgmolisani, |
Also want to get opinions on adding the complete document AST to the gatsby-source-contentful schema for rich text. Since we can't put any JSX in our gatsby-config or -node files, the only way to use I'm no Gatsby plugin expert, but I try to do my homework. The following code in the gatsby-node.js file should add the full document tree as an object to the GraphQL node. Took the naming convention from the remark transformer package. // gatsby-node.js
const { GraphQLJSON } = require('gatsby/graphql');
exports.setFieldsOnGraphQLNodeType = ({ type }) => {
if (type.name.match(/contentful.*RichTextNode/)) {
return {
contentAST: {
type: GraphQLJSON,
resolve: source => {
// Can also use source.content here, not sure what is best practice vs. most performant
// or if there are gotchas with one or the other
return JSON.parse(source.internal.content);
}
}
};
}
return {};
}; Then, you could just use: documentToReactTree(data.contenfulStuff.key.contentAST, options) Not saying this saves a ton of time typing, but to me it feels cleaner than expecting the developer to parse JSON for use with Gatsby and potentially touching the |
@mgmolisani just using this now for a project. its working out quite nicely. nice work so far! excited to have this as native in the project |
Here is a gist of the same code but with caching. I have no way to tell if caching has any improvement on load time so if you have a beefy rich text node, give it a go. I also noticed Gatsby uses a cache manager that says it resolves with what was stored in the cache... but it actually doesn't which you might better understand from my gist comments. I opened an issue with Gatsby here (which was confirmed in like minutes - go Gatsby!) if you want to help with that. |
Having a pretty hard time getting the repo going as |
Hi @mgmolisani, I think it's better to use yarn with the monorepo instead of npm |
Still no luck with a new clone and Consistently getting this error in many tests: 1 import { Document, Node, Block, Link, NodeData } from '@contentful/rich-text-types';
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Build seemed to be successful with only 1 hoisting warning. $ lerna bootstrap --hoist --progress --no-ci
lerna notice cli v3.10.7
lerna info Bootstrapping 6 packages
lerna WARN EHOIST_ROOT_VERSION The repository root depends on @types/jest@^23.3.8, which differs from the more common @types/jest@^23.3.12.
lerna WARN EHOIST_PKG_VERSION "@contentful/rich-text-types" package depends on @types/jest@^23.3.12, which differs from the hoisted @types/jest@^23.3.8.
lerna info Installing external dependencies
lerna info hoist Installing hoisted dependencies into root
lerna info hoist Pruning hoisted dependencies
lerna info hoist Finished pruning hoisted dependencies
lerna info hoist Finished bootstrapping root
lerna info Symlinking packages and binaries
lerna info lifecycle @contentful/[email protected]~prepare: @contentful/[email protected] Is there anything else I could provide that might help assess? Maybe I'm missing a global package? Any thoughts? |
Interesting discussion though it's hard for me to fully grasp
Could someone here address those questions? |
Other stuff is just me trying to make the current Gatsby source plugin more usable by all the packages. I am waiting on a pull request getting approved by the Gatsby team (however, that has hit a few road blocks due to potentially breaking changes, so it's back with me for small edits). |
Not exactly what this issue was about since this isn't Gatsby specific but |
That's great! I've been waiting for this! How would I use that in a Gatsby project? Do I still include |
Here is an example of a helper component for consuming this document (I may make a PR to add this to the package). import PropTypes from 'prop-types';
import { documentToReactComponents } from '@contentful/rich-text-react-renderer';
const RichText = ({ document, options }) => {
return documentToReactComponents(document, options);
};
RichText.propTypes = {
document: PropTypes.object,
options: PropTypes.object,
};
export default RichText;
No. Since JSX is not transpiled in the node and config files (without some serious work arounds anyway), you have to handle this outside the plugin. You will only need the source plugin to get the stringified AST as described above. There is PR for this based on this gist to add the JSON AST in the source plugin so parsing will not be necessary in the future. |
@mgmolisani Thanks for the quick response! That's basically what I'm doing (I think, since didn't get the
Here's a stripped-down version of my code. Can you see what I'm doing wrong? import React from "react"
import { graphql } from "gatsby"
import { BLOCKS } from "@contentful/rich-text-types"
import { documentToReactComponents } from "@contentful/rich-text-react-renderer"
import PageTitle from "../components/PageTitle"
const Person = ({ name }) => <h2>{name}</h2>
const options = {
renderNode: {
[BLOCKS.EMBEDDED_ENTRY]: node => {
const { name } = node.data.target.fields
return <Person name={name.de} />
},
},
}
const PageTemplate = ({ data }) => {
const { title, richBody } = data.page
richBody && console.log(documentToReactComponents(richBody, options))
return (
<PageTitle>
<h1>{title}</h1>
</PageTitle>
)
}
export default PageTemplate
export const query = graphql`
query($slug: String!) {
page: contentfulPage(slug: { eq: $slug }) {
title
richBody {
nodeType
content {
nodeType
data {
target {
fields {
name {
de
}
}
}
}
}
}
}
}
` |
@janosh Partial trees will likely cause errors with default renderers. In your case, the single paragraph tag is trying to access In your graphql query
And this in the document arg: JSON.parse(richBody.richBody) // This is the `key.key` part I was talking about Soon, |
Awesome! Thanks so much for your help! Never would have thought of |
@mgmolisani Do you know if there is or will be a way to transform data on rich text embedded entries? E.g. format date strings with The date formatting I assume can already be done by including it into the GraphQL query explicitly rather than just requesting |
@janosh I will try to answer these here but you may want to ask some of these in the community Slack channel as they are deviating from this thread. I also do not know Contentful's plans for the future.
This renderer exposes the raw node as the first argument in the callback for exactly this reason. On the entry type of your choosing, pass the date as a prop and handle that prop in your React component however you like (i.e. run it through formatter and display it as children). // Embed.jsx
const Embed = ({date}) => {
return <h6>{format(date)}</h6>;
};
// Wherever you put your renderer
const options = {
renderNode: {
[BLOCKS.EMBEDDED_ENTRY]: node => {
return <Embed date={node.path.to.date} />
},
},
}
Look into
I think the source package already does this? Maybe not in the embeds though? If it doesn't, you could probably handle it with a second query on the ID. Not sure, haven't run into a time where I wanted Images as part of my rich text (although I know others do). I actually prefer making 'slices' (many nested references) and pulling more complex structures like lists and images out of the rich text only giving users control over the inline things like marks and links. Check out this page for more gatsby-image info and support.
Sounds painful to implement using SaaS instead of your own backend or middleware. You'd have to know very early on you want this to to implement it in every component (either hardcoded or using context). It may be better when making your queries to handle it there or make a transformer plugin to handle it in the specific locations you know it will occur (after all, you build the queries). I can't imagine your main content is dates though so the refactor shouldn't be too stressful if your components are sufficiently separating their duties. |
When can I found a test repository to see how the code is impletemented please ? |
Hello there, I am Contentful's product manager working on our Rich Text editor and we recently released an improvement in the Thank you and let me know if that works. |
@martzoukos Very cool! I'm excited to start using Contentful Rich Text in production. Not sure I understand you correctly, though. Does
give me any additional data that wasn't resolved before in
|
@janosh |
Will be closing this issue due to the deprecation of Feel free to ask any further questions in our community slack channel or send them me directly. |
@mgmolisani would you know why I can only query the second one of those examples, and when I query |
@skarges3 are you using the most up to date source package? |
I am wondering what is the correct way to use react with the plugin configuration.
I need to use a gatsby Link component for INLINES.ENTRY_HYPERLINK and not sure how to do so from the gatsby-config file or if there is some other workaround. I have lots of other use cases for using a react component as well.
Can anyone point me in the right direction?
The text was updated successfully, but these errors were encountered: