Skip to content

Commit

Permalink
feat(SSR): add support for initial SSR render support
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker committed May 30, 2022
1 parent e21fd33 commit eb0610d
Show file tree
Hide file tree
Showing 6 changed files with 389 additions and 57 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ It supports these props, while passing any others through to the `children`:
|code|PropTypes.string|The code that should be rendered, apart from the user’s edits
|scope|PropTypes.object|Accepts custom globals that the `code` can use
|noInline|PropTypes.bool|Doesn’t evaluate and mount the inline code (Default: `false`). Note: when using `noInline` whatever code you write must be a single expression (function, class component or some `jsx`) that can be returned immediately. If you'd like to render multiple components, use `noInline={true}`
|skipInitialRender|PropTypes.bool|Skip the initial render used for SSR (Default: `false`)
|transformCode|PropTypes.func|Accepts and returns the code to be transpiled, affording an opportunity to first transform it
|language|PropTypes.string|What language you're writing for correct syntax highlighting. (Default: `jsx`)
|disabled|PropTypes.bool|Disable editing on the `<LiveEditor />` (Default: `false`)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"use-editable": "^2.3.3"
},
"devDependencies": {
"@testing-library/react": "^12.1.5",
"@babel/core": "^7.15.0",
"@babel/eslint-parser": "^7.15.0",
"@babel/plugin-proposal-class-properties": "^7.14.5",
Expand Down Expand Up @@ -90,7 +91,6 @@
],
"jest": {
"testEnvironment": "jsdom",
"resetMocks": true,
"rootDir": "./src",
"testURL": "http://localhost/"
},
Expand Down
57 changes: 52 additions & 5 deletions src/components/Live/LiveProvider.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react";
import React, { useEffect, useState, useRef } from "react";
import PropTypes from "prop-types";

import LiveContext from "./LiveContext";
Expand All @@ -13,13 +13,58 @@ function LiveProvider({
scope,
transformCode,
noInline = false,
skipInitialRender = false,
}) {
const [state, setState] = useState({
error: undefined,
element: undefined,
});
// avoid to render code twice when rendered initially (ssr)
const cache = useRef("initial");

// ssr render the code in sync
const [state, setState] = useState(() => transpileSync(code));

function transpileSync(code) {
const returnObject = {
element: undefined,
error: undefined,
};

if (!skipInitialRender) {
const renderElement = (element) => {
return (returnObject.element = element);
};
const errorCallback = (error) => {
return (returnObject.error = error);
};

try {
const transformResult = transformCode ? transformCode(code) : code;

// Transpilation arguments
const input = {
code: transformResult,
scope,
};

if (noInline) {
renderElementAsync(input, renderElement, errorCallback);
} else {
renderElement(generateElement(input, errorCallback));
}

cache.current = code;
} catch (e) {
errorCallback(e);
}
}

return returnObject;
}

function transpileAsync(newCode) {
if (cache.current === newCode) {
cache.current = "used"; // do not check for null or undefined, in case the new code is such
return Promise.resolve();
}

const errorCallback = (error) => {
setState({ error: error.toString(), element: undefined });
};
Expand Down Expand Up @@ -92,13 +137,15 @@ LiveProvider.propTypes = {
language: PropTypes.string,
noInline: PropTypes.bool,
scope: PropTypes.object,
skipInitialRender: PropTypes.bool,
theme: PropTypes.object,
transformCode: PropTypes.func,
};

LiveProvider.defaultProps = {
code: "",
noInline: false,
skipInitialRender: false,
language: "jsx",
disabled: false,
};
Expand Down
Loading

0 comments on commit eb0610d

Please sign in to comment.