Skip to content

Commit 381f4e7

Browse files
committed
Change unique id generation for compatibility with SSR
1 parent c059f4b commit 381f4e7

File tree

5 files changed

+68
-26
lines changed

5 files changed

+68
-26
lines changed

nextjs-demo/pages/index.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,11 @@ export default function Home() {
1010
<meta name="viewport" content="width=device-width, initial-scale=1" />
1111
<link rel="icon" href="/favicon.ico" />
1212
</Head>
13-
<Space.ViewPort id="viewport">
14-
<Space.LeftResizable id="left" size="25%" centerContent={Space.CenterType.HorizontalVertical} style={{ backgroundColor: "white" }}>
13+
<Space.ViewPort>
14+
<Space.LeftResizable size="25%" centerContent={Space.CenterType.HorizontalVertical} style={{ backgroundColor: "white" }}>
1515
<span style={{ color: "black" }}>Hello world</span>
1616
</Space.LeftResizable>
17-
<Space.Fill id="fill" centerContent={Space.CenterType.HorizontalVertical}>
18-
Hello world
19-
</Space.Fill>
17+
<Space.Fill centerContent={Space.CenterType.HorizontalVertical}>Hello world</Space.Fill>
2018
</Space.ViewPort>
2119
</>
2220
);

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@
2828
"description": "An easy to understand and nestable layout system, React Spaces allow you to divide a page or container into anchored, scrollable and resizable spaces enabling you to build desktop type user interfaces in the browser.",
2929
"dependencies": {
3030
"css-element-queries": "^1.2.1",
31-
"prop-types": "^15.7.2",
32-
"react-spaces": "file:../dist"
31+
"prop-types": "^15.7.2"
3332
},
3433
"devDependencies": {
3534
"@babel/core": "^7.5.5",

src/components/Space.tsx

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
import { CenterType, ResizeHandlePlacement, AnchorType, Type } from "../core-types";
2-
import { useSpace, ParentContext, LayerContext, DOMRectContext, IReactSpaceInnerProps, useEffectOnce, SSR_SUPPORT_ENABLED } from "../core-react";
2+
import {
3+
useSpace,
4+
ParentContext,
5+
LayerContext,
6+
DOMRectContext,
7+
IReactSpaceInnerProps,
8+
useEffectOnce,
9+
SSR_SUPPORT_ENABLED,
10+
useUniqueId,
11+
} from "../core-react";
312
import * as React from "react";
413
import { Centered } from "./Centered";
514
import { CenteredVertically } from "./CenteredVertically";
6-
import { shortuuid, updateStyleDefinition } from "../core-utils";
15+
import { updateStyleDefinition } from "../core-utils";
716

817
function applyCentering(children: React.ReactNode, centerType: CenterType | undefined) {
918
switch (centerType) {
@@ -22,8 +31,13 @@ export class Space extends React.Component<IReactSpaceInnerProps> {
2231
}
2332

2433
const SpaceInner: React.FC<IReactSpaceInnerProps & { wrapperInstance: Space }> = (props) => {
25-
if (!props.id && !props.wrapperInstance["_react_spaces_uniqueid"]) {
26-
props.wrapperInstance["_react_spaces_uniqueid"] = `s${shortuuid()}`;
34+
let idToUse = props.id ?? props.wrapperInstance["_react_spaces_uniqueid"];
35+
36+
const uniqueId = useUniqueId();
37+
38+
if (!idToUse) {
39+
props.wrapperInstance["_react_spaces_uniqueid"] = uniqueId;
40+
idToUse = props.wrapperInstance["_react_spaces_uniqueid"];
2741
}
2842

2943
const {
@@ -56,7 +70,7 @@ const SpaceInner: React.FC<IReactSpaceInnerProps & { wrapperInstance: Space }> =
5670

5771
const { space, domRect, elementRef, resizeHandles } = useSpace({
5872
...props,
59-
...{ id: props.id || props.wrapperInstance["_react_spaces_uniqueid"] },
73+
...{ id: idToUse },
6074
});
6175

6276
useEffectOnce(() => {
@@ -66,6 +80,12 @@ const SpaceInner: React.FC<IReactSpaceInnerProps & { wrapperInstance: Space }> =
6680
if (space.element.getAttribute("data-ssr") === "1") {
6781
const preRenderedStyle = space.element.children[0];
6882
if (preRenderedStyle) {
83+
const id = preRenderedStyle.getAttribute("data-id");
84+
if (id) {
85+
space.id = id;
86+
console.log(space.id);
87+
}
88+
6989
const newStyle = document.createElement("style");
7090
newStyle.id = `style_${space.id}`;
7191
newStyle.innerHTML = preRenderedStyle.innerHTML;
@@ -123,7 +143,11 @@ const SpaceInner: React.FC<IReactSpaceInnerProps & { wrapperInstance: Space }> =
123143
props.as || "div",
124144
outerProps,
125145
<>
126-
{SSR_SUPPORT_ENABLED && space.ssrStyle && <style className="ssr">{space.ssrStyle}</style>}
146+
{SSR_SUPPORT_ENABLED && space.ssrStyle && (
147+
<style className="ssr" data-id={space.id}>
148+
{space.ssrStyle}
149+
</style>
150+
)}
127151
<div className={innerClasses.join(" ")} style={innerStyle}>
128152
<ParentContext.Provider value={space.id}>
129153
<LayerContext.Provider value={undefined}>

src/core-react.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,26 @@ export function useForceUpdate() {
117117
}, []);
118118
}
119119

120+
export function useUniqueId() {
121+
if (React.version.startsWith("18")) {
122+
return `s${React.useId().replace(/\:/g, "")}`;
123+
}
124+
125+
if ((React as any).unstable_useOpaqueIdentifier) {
126+
return `s${(React as any).unstable_useOpaqueIdentifier().replace(/\:/g, "")}`;
127+
}
128+
129+
return `s${shortuuid()}`;
130+
}
131+
120132
export function useSpace(props: IReactSpaceInnerProps) {
121133
const store = currentStore;
122134
const update = useForceUpdate();
123135
const parent = React.useContext(ParentContext);
124136
const layer = React.useContext(LayerContext);
125137
const { debug } = React.useContext(OptionsContext);
126-
const [spaceId] = React.useState(props.id || `s${shortuuid()}`);
138+
const uniqueId = useUniqueId();
139+
const [spaceId] = React.useState(props.id || uniqueId);
127140
const elementRef = React.useRef<HTMLElement>();
128141
const resizeSensor = React.useRef<ResizeSensor>();
129142
const [domRect, setDomRect] = React.useState<DOMRect>();
@@ -277,6 +290,7 @@ export function useCurrentSpace() {
277290
}
278291

279292
export let SSR_SUPPORT_ENABLED = false;
293+
280294
export function enabledSsrSupport() {
281295
SSR_SUPPORT_ENABLED = true;
282296
}

src/core-utils.ts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -395,20 +395,18 @@ export function styleDefinition(space: ISpaceDefinition) {
395395

396396
export function updateStyleDefinition(space: ISpaceDefinition) {
397397
const definition = styleDefinition(space);
398-
if (typeof document !== "undefined") {
399-
if (document) {
400-
const existing = document.getElementById(`style_${space.id}`);
398+
if (!isServer()) {
399+
const existing = document.getElementById(`style_${space.id}`);
401400

402-
if (existing) {
403-
if (existing.innerHTML !== definition) {
404-
existing.innerHTML = definition;
405-
}
406-
} else {
407-
const newStyle = document.createElement("style");
408-
newStyle.id = `style_${space.id}`;
409-
newStyle.innerHTML = definition;
410-
document.head.appendChild(newStyle);
401+
if (existing) {
402+
if (existing.innerHTML !== definition) {
403+
existing.innerHTML = definition;
411404
}
405+
} else {
406+
const newStyle = document.createElement("style");
407+
newStyle.id = `style_${space.id}`;
408+
newStyle.innerHTML = definition;
409+
document.head.appendChild(newStyle);
412410
}
413411
}
414412
}
@@ -419,3 +417,12 @@ export function removeStyleDefinition(space: ISpaceDefinition) {
419417
document.head.removeChild(existing);
420418
}
421419
}
420+
421+
export function isServer() {
422+
if (typeof document !== "undefined") {
423+
if (document) {
424+
return false;
425+
}
426+
}
427+
return true;
428+
}

0 commit comments

Comments
 (0)