![PyPI Now Supports iOS and Android Wheels for Mobile Python Development](https://cdn.sanity.io/images/cgdhsj6q/production/96416c872705517a6a65ad9646ce3e7caef623a0-1024x1024.webp?w=400&fit=max&auto=format)
Security News
PyPI Now Supports iOS and Android Wheels for Mobile Python Development
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
react-datocms
Advanced tools
![MIT](https://img.shields.io/npm/l/react-datocms?style=for-the-badge) ![MIT](https://img.shields.io/npm/v/react-datocms?style=for-the-badge) [![Build Status](https://img.shields.io/travis/datocms/react-datocms?style=for-the-badge)](https://travis-ci.org/
A set of components and utilities to work faster with DatoCMS in React environments. Integrates seamlessy with DatoCMS's GraphQL Content Delivery API and Real-time Updates API.
For fully working examples take a look at our examples directory.
Live demo: https://react-datocms-example.netlify.com/
npm install react-datocms
useQuerySubscription
is a React hook that you can use to implement client-side updates of the page as soon as the content changes. It uses DatoCMS's Real-time Updates API to receive the updated query results in real-time, and is able to reconnect in case of network failures.
Live updates are great both to get instant previews of your content while editing it inside DatoCMS, or to offer real-time updates of content to your visitors (ie. news site).
Import useQuerySubscription
from react-datocms
and use it inside your components like this:
const {
data: QueryResult | undefined,
error: ChannelErrorData | null,
status: ConnectionStatus,
} = useQuerySubscription(options: Options);
prop | type | required | description | default |
---|---|---|---|---|
enabled | boolean | :x: | Whether the subscription has to be performed or not | true |
query | string | :white_check_mark: | The GraphQL query to subscribe | |
token | string | :white_check_mark: | DatoCMS API token to use | |
variables | Object | :x: | GraphQL variables for the query | |
preview | boolean | :x: | If true, the Content Delivery API with draft content will be used | false |
environment | string | :x: | The name of the DatoCMS environment where to perform the query | defaults to primary environment |
initialData | Object | :x: | The initial data to use on the first render | |
reconnectionPeriod | number | :x: | In case of network errors, the period (in ms) to wait to reconnect | 1000 |
fetcher | a fetch-like function | :x: | The fetch function to use to perform the registration query | window.fetch |
eventSourceClass | an EventSource-like class | :x: | The EventSource class to use to open up the SSE connection | window.EventSource |
baseUrl | string | :x: | The base URL to use to perform the query | https://graphql-listen.datocms.com |
The status
property represents the state of the server-sent events connection. It can be one of the following:
connecting
: the subscription channel is trying to connectconnected
: the channel is open, we're receiving live updatesclosed
: the channel has been permanently closed due to a fatal error (ie. an invalid query)prop | type | description |
---|---|---|
code | string | The code of the error (ie. INVALID_QUERY ) |
message | string | An human friendly message explaining the error |
response | Object | The raw response returned by the endpoint, if available |
import React from 'react';
import { useQuerySubscription } from 'react-datocms';
const App: React.FC = () => {
const { status, error, data } = useQuerySubscription({
enabled: true,
query: `
query AppQuery($first: IntType) {
allBlogPosts {
slug
title
}
}`,
variables: { first: 10 },
token: 'YOUR_API_TOKEN',
});
const statusMessage = {
connecting: 'Connecting to DatoCMS...',
connected: 'Connected to DatoCMS, receiving live updates!',
closed: 'Connection closed',
};
return (
<div>
<p>Connection status: {statusMessage[status]}</p>
{error && (
<div>
<h1>Error: {error.code}</h1>
<div>{error.message}</div>
{error.response && (
<pre>{JSON.stringify(error.response, null, 2)}</pre>
)}
</div>
)}
{data && (
<ul>
{data.allBlogPosts.map((blogPost) => (
<li key={blogPost.slug}>{blogPost.title}</li>
))}
</ul>
)}
</div>
);
};
<Image />
is a React component specially designed to work seamlessly with DatoCMS’s responsiveImage
GraphQL query that optimizes image loading for your sites.
Image
from react-datocms
and use it in place of the regular <img />
tagresponsiveImage
queryThe GraphQL query returns multiple thumbnails with optimized compression. The Image
component automatically sets up the “blur-up” effect as well as lazy loading of images further down the screen.
For a fully working example take a look at our examples directory.
import React from 'react';
import { Image } from 'react-datocms';
const Page = ({ data }) => (
<div>
<h1>{data.blogPost.title}</h1>
<Image data={data.blogPost.cover.responsiveImage} />
</div>
);
const query = gql`
query {
blogPost {
title
cover {
responsiveImage(
imgixParams: { fit: crop, w: 300, h: 300, auto: format }
) {
# HTML5 src/srcset/sizes attributes
srcSet
webpSrcSet
sizes
src
# size information (post-transformations)
width
height
aspectRatio
# SEO attributes
alt
title
# background color placeholder or...
bgColor
# blur-up placeholder, JPEG format, base64-encoded
base64
}
}
}
}
`;
export default withQuery(query)(Page);
prop | type | required | description | default |
---|---|---|---|---|
data | ResponsiveImage object | :white_check_mark: | The actual response you get from a DatoCMS responsiveImage GraphQL query. | |
className | string | :x: | Additional CSS className for root node | null |
style | CSS properties | :x: | Additional CSS rules to add to the root node | null |
pictureClassName | string | :x: | Additional CSS class for the image inside the inner <picture /> tag | null |
pictureStyle | CSS properties | :x: | Additional CSS rules to add to the image inside the inner <picture /> tag | null |
fadeInDuration | integer | :x: | Duration (in ms) of the fade-in transition effect upoad image loading | 500 |
intersectionThreshold | float | :x: | Indicate at what percentage of the placeholder visibility the loading of the image should be triggered. A value of 0 means that as soon as even one pixel is visible, the callback will be run. A value of 1.0 means that the threshold isn't considered passed until every pixel is visible. | 0 |
intersectionMargin | string | :x: | Margin around the placeholder. Can have values similar to the CSS margin property (top, right, bottom, left). The values can be percentages. This set of values serves to grow or shrink each side of the placeholder element's bounding box before computing intersections. | "0px 0px 0px 0px" |
lazyLoad | Boolean | :x: | Wheter enable lazy loading or not | true |
explicitWidth | Boolean | :x: | Wheter the image wrapper should explicitely declare the width of the image or keep it fluid | false |
ResponsiveImage
objectThe data
prop expects an object with the same shape as the one returned by responsiveImage
GraphQL call. It's up to you to make a GraphQL query that will return the properties you need for a specific use of the <Image>
component.
data
are: aspectRatio
, width
, sizes
, srcSet
and src
;alt
and title
, while not mandatory, are all highly suggested, so remember to use them!webpSrcSet
field or specify { auto: format }
in your imgixParams
, to automatically use WebP images in browsers that support the format;bgColor
and base64
property, the latter will take precedence, so just avoiding querying both fields at the same time, it will only make the response bigger :wink:Here's a complete recap of what responsiveImage
offers:
property | type | required | description |
---|---|---|---|
aspectRatio | float | :white_check_mark: | The aspect ratio (width/height) of the image |
width | integer | :white_check_mark: | The width of the image |
height | integer | :white_check_mark: | The height of the image |
sizes | string | :white_check_mark: | The HTML5 sizes attribute for the image |
srcSet | string | :white_check_mark: | The HTML5 srcSet attribute for the image |
src | string | :white_check_mark: | The fallback src attribute for the image |
webpSrcSet | string | :x: | The HTML5 srcSet attribute for the image in WebP format, for browsers that support the format |
alt | string | :x: | Alternate text (alt ) for the image |
title | string | :x: | Title attribute (title ) for the image |
bgColor | string | :x: | The background color for the image placeholder |
base64 | string | :x: | A base64-encoded thumbnail to offer during image loading |
Just like the image component, renderMetaTags()
is a helper specially designed to work seamlessly with DatoCMS’s _seoMetaTags
and faviconMetaTags
GraphQL queries so that you can handle proper SEO in your pages with a simple one-liner.
renderMetaTags()
takes an array of Tag
s in the exact form they're returned by the following DatoCMS GraphQL API queries:
_seoMetaTags
query on any record, orfaviconMetaTags
on the global _site
object.You can concat
multiple array of Tag
s together and pass them to a single renderMetaTags()
call.
For a working example take a look at our examples directory.
import React from 'react';
import { renderMetaTags } from 'react-datocms';
const Page = ({ data }) => (
<div>
<Helmet>{renderMetaTags(data.page.seo.concat(data.site.favicon))}</Helmet>
<h1>{data.page.title}</h1>
</div>
);
const query = gql`
query {
page: homepage {
title
seo: _seoMetaTags {
attributes
content
tag
}
}
site: _site {
favicon: faviconMetaTags {
attributes
content
tag
}
}
}
`;
export default withQuery(query)(Page);
<StructuredText />
is a React component that you can use to render the value contained inside a DatoCMS Structured Text field type.
import React from 'react';
import { StructuredText } from 'react-datocms';
const Page = ({ data }) => {
// data.blogPost.content ->
// {
// value: {
// schema: "dast",
// document: {
// type: "root",
// children: [
// {
// type: "heading",
// level: 1,
// children: [
// {
// type: "span",
// value: "Hello ",
// },
// {
// type: "span",
// marks: ["strong"],
// value: "world!",
// },
// ],
// },
// ],
// },
// },
// }
return (
<div>
<h1>{data.blogPost.title}</h1>
<StructuredText data={data.blogPost.content} />
{/* -> <h1>Hello <strong>world!</strong></h1> */}
</div>
);
};
const query = gql`
query {
blogPost {
title
content {
value
}
}
}
`;
export default withQuery(query)(Page);
You can also pass custom renderers for special nodes (inline records, record links and blocks) as an optional parameter like so:
import React from 'react';
import { StructuredText, Image } from 'react-datocms';
const Page = ({ data }) => {
// data.blogPost.content ->
// {
// value: {
// schema: "dast",
// document: {
// type: "root",
// children: [
// {
// type: "heading",
// level: 1,
// children: [
// { type: "span", value: "Welcome onboard " },
// { type: "inlineItem", item: "324321" },
// ],
// },
// {
// type: "paragraph",
// children: [
// { type: "span", value: "So happy to have " },
// {
// type: "itemLink",
// item: "324321",
// children: [
// {
// type: "span",
// marks: ["strong"],
// value: "this awesome humang being",
// },
// ]
// },
// { type: "span", value: " in our team!" },
// ]
// },
// { type: "block", item: "1984559" }
// ],
// },
// },
// links: [
// {
// id: "324321",
// __typename: "TeamMemberRecord",
// firstName: "Mark",
// slug: "mark-smith",
// },
// ],
// blocks: [
// {
// id: "324321",
// __typename: "ImageRecord",
// image: {
// responsiveImage: { ... },
// },
// },
// ],
// }
return (
<div>
<h1>{data.blogPost.title}</h1>
<StructuredText
data={data.blogPost.content}
renderInlineRecord={({ record }) => {
switch (record.__typename) {
case 'TeamMemberRecord':
return <a href={`/team/${record.slug}`}>{record.firstName}</a>;
default:
return null;
}
}}
renderLinkToRecord={({ record, children, transformedMeta }) => {
switch (record.__typename) {
case 'TeamMemberRecord':
return (
<a {...transformedMeta} href={`/team/${record.slug}`}>
{children}
</a>
);
default:
return null;
}
}}
renderBlock={({ record }) => {
switch (record.__typename) {
case 'ImageRecord':
return <Image data={record.image.responsiveImage} />;
default:
return null;
}
}}
/>
{/*
Final result:
<h1>Welcome onboard <a href="/team/mark-smith">Mark</a></h1>
<p>So happy to have <a href="/team/mark-smith">this awesome humang being</a> in our team!</p>
<img src="https://www.datocms-assets.com/205/1597757278-austin-distel-wd1lrb9oeeo-unsplash.jpg" alt="Our team at work" />
*/}
</div>
);
};
const query = gql`
query {
blogPost {
title
content {
value
links {
__typename
... on TeamMemberRecord {
id
firstName
slug
}
}
blocks {
__typename
... on ImageRecord {
id
image {
responsiveImage(
imgixParams: { fit: crop, w: 300, h: 300, auto: format }
) {
srcSet
webpSrcSet
sizes
src
width
height
aspectRatio
alt
title
base64
}
}
}
}
}
}
}
`;
export default withQuery(query)(Page);
This component automatically renders all nodes except for inline_item
, item_link
and block
using a set of default rules, but you might want to customize those. For example:
For example:
For heading
nodes, you might want to add an anchor;
For code
nodes, you might want to use a custom sytax highlighting component like prism-react-renderer
;
Apply different logic/formatting to a node based on what its parent node is (using the ancestors
parameter)
For all possible node types, refer to the list of typeguard functions defined in the main structured-text
package. The DAST format documentation has additional details.
In this case, you can easily override default rendering rules with the customRules
prop.
import { renderRule, StructuredText } from 'react-datocms';
import { isHeading, isCode } from 'datocms-structured-text-utils';
import { render as toPlainText } from 'datocms-structured-text-to-plain-text';
import SyntaxHighlight from 'components/SyntaxHighlight';
<StructuredText
data={data.blogPost.content}
customRules={[
// Add HTML anchors to heading levels for in-page navigation
renderRule(isHeading, ({ node, children, key }) => {
const HeadingTag = `h${node.level}`;
const anchor = toPlainText(node)
.toLowerCase()
.replace(/ /g, '-')
.replace(/[^\w-]+/g, '');
return (
<HeadingTag key={key}>
{children} <a id={anchor} />
<a href={`#${anchor}`} />
</HeadingTag>
);
}),
// Use a custom syntax highlighter component for code blocks
renderRule(isCode, ({ node, key }) => {
return (
<SyntaxHighlight
key={key}
code={node.code}
language={node.language}
linesToBeHighlighted={node.highlight}
/>
);
}),
// Apply different formatting to top-level paragraphs
renderRule(
isParagraph,
({ adapter: { renderNode }, node, children, key, ancestors }) => {
if (isRoot(ancestors[0])) {
// If this paragraph node is a top-level one, give it a special class
return renderNode('p', { key, className: 'top-level-paragraph-container-example' }, children);
} else {
// Proceed with default paragraph rendering...
// return renderNode('p', { key }, children);
// Or even completely remove the paragraph and directly render the inner children:
return children;
}
}
)
]}
/>;
Note: if you override the rules for inline_item
, item_link
or block
nodes, then the renderInlineRecord
, renderLinkToRecord
and renderBlock
props won't be considered!
prop | type | required | description | default |
---|---|---|---|---|
data | StructuredTextGraphQlResponse | DastNode | :white_check_mark: | The actual field value you get from DatoCMS | |
renderInlineRecord | ({ record }) => ReactElement | null | Only required if document contains inlineItem nodes | Convert an inlineItem DAST node into React | [] |
renderLinkToRecord | ({ record, children }) => ReactElement | null | Only required if document contains itemLink nodes | Convert an itemLink DAST node into React | null |
renderBlock | ({ record }) => ReactElement | null | Only required if document contains block nodes | Convert a block DAST node into React | null |
metaTransformer | ({ node, meta }) => Object | null | :x: | Transform link and itemLink meta property into HTML props | See function |
customRules | Array<RenderRule> | :x: | Customize how document is converted in JSX (use renderRule() to generate) | null |
renderText | (text: string, key: string) => ReactElement | string | null | :x: | Convert a simple string text into React | (text) => text |
FAQs
<!--datocms-autoinclude-header start-->
The npm package react-datocms receives a total of 30,630 weekly downloads. As such, react-datocms popularity was classified as popular.
We found that react-datocms demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 6 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
Security News
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.