Skip to content

Commit c9ad618

Browse files
committed
Provided implementation that auto generates a space ID that persists between double renders caused by using <React.StrictMode></React.StrictMode> by storing it in a wrapper class component instance.
1 parent 56a6146 commit c9ad618

File tree

8 files changed

+118
-79
lines changed

8 files changed

+118
-79
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-spaces",
3-
"version": "0.2.0-beta.2",
3+
"version": "0.2.0-beta.3",
44
"main": "dist/index.js",
55
"module": "dist/es/index.js",
66
"types": "dist/index.d.ts",

src/components/Options.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import * as React from "react";
2+
import { IReactSpacesOptions, OptionsContext } from "../core-react";
3+
4+
export const Options: React.FC<IReactSpacesOptions> = ({ children, ...opts }) => {
5+
return <OptionsContext.Provider value={opts}>{children}</OptionsContext.Provider>;
6+
};

src/components/Space.tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useSpace, ParentContext, LayerContext, DOMRectContext } from "../core-r
33
import * as React from "react";
44
import { Centered } from "./Centered";
55
import { CenteredVertically } from "./CenteredVertically";
6+
import { shortuuid } from "../core-utils";
67

78
function applyCentering(children: React.ReactNode, centerType: CenterType | undefined) {
89
switch (centerType) {
@@ -14,7 +15,17 @@ function applyCentering(children: React.ReactNode, centerType: CenterType | unde
1415
return children;
1516
}
1617

17-
export const Space: React.FC<ISpaceProps> = (props) => {
18+
export class Space extends React.Component<ISpaceProps> {
19+
public render() {
20+
return <SpaceInner {...this.props} wrapperInstance={this} />;
21+
}
22+
}
23+
24+
const SpaceInner: React.FC<ISpaceProps & { wrapperInstance: Space }> = (props) => {
25+
if (!props.id && !props.wrapperInstance["_react_spaces_uniqueid"]) {
26+
props.wrapperInstance["_react_spaces_uniqueid"] = `s${shortuuid()}`;
27+
}
28+
1829
const {
1930
style,
2031
className,
@@ -42,7 +53,10 @@ export const Space: React.FC<ISpaceProps> = (props) => {
4253
onTouchEnd: onTouchEnd,
4354
};
4455

45-
const { space, domRect, elementRef, resizeHandles } = useSpace(props);
56+
const { space, domRect, elementRef, resizeHandles } = useSpace({
57+
...props,
58+
...{ id: props.id || props.wrapperInstance["_react_spaces_uniqueid"] },
59+
});
4660

4761
React.useEffect(() => {
4862
space.element = elementRef.current!;

src/components/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ export * from "./Layer";
1010
export * from "./Positioned";
1111
export * from "./SpaceInfo";
1212
export * from "./ViewPort";
13+
export * from "./Options";
1314
export { AnchorType, CenterType, IPosition } from "../core-types";

src/components/stories/00-docs/01-GettingStarted.stories.mdx

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Meta, Story, Preview, Props } from "@storybook/addon-docs/blocks";
22
import { CommonHeader, DemoUI } from "../Utils";
3-
import { CenterType, ViewPort, Fixed, Top, Right, LeftResizable, BottomResizable, Fill } from "../../";
3+
import { CenterType, ViewPort, Fixed, Top, Right, LeftResizable, BottomResizable, Fill, Options } from "../../";
44

55
<CommonHeader />
66

@@ -47,14 +47,16 @@ lines and text alignment have been added specifically for this example. In pract
4747
have any visual element, padding or margins leaving it up to you to fill them or style them however
4848
you want.*
4949

50-
<Fixed style={{ outline: '1px solid black' }} height={400}>
51-
<LeftResizable style={{ borderRight: '1px dashed black' }} size="25%" centerContent={CenterType.HorizontalVertical}>
52-
Sidebar
53-
</LeftResizable>
54-
<Fill centerContent={CenterType.HorizontalVertical}>
55-
Main content
56-
</Fill>
57-
</Fixed>
50+
<React.StrictMode>
51+
<Fixed style={{ outline: '1px solid black' }} height={400}>
52+
<LeftResizable style={{ borderRight: '1px dashed black' }} size="25%" centerContent={CenterType.HorizontalVertical}>
53+
Sidebar
54+
</LeftResizable>
55+
<Fill centerContent={CenterType.HorizontalVertical}>
56+
Main content
57+
</Fill>
58+
</Fixed>
59+
</React.StrictMode>
5860

5961
Notice how the fill space automatically adjusts it's size when the left resizable space is resized with
6062
the mouse.
@@ -85,19 +87,21 @@ const App = () => (
8587

8688
Here we have added additional nested spaces inside the original `<Fill />` space to achieve this:
8789

88-
<Fixed style={{ outline: '1px solid black' }} height={400}>
89-
<LeftResizable style={{ borderRight: '1px dashed black' }} size="25%" centerContent={CenterType.HorizontalVertical}>
90-
Sidebar
91-
</LeftResizable>
92-
<Fill>
93-
<Fill centerContent={CenterType.HorizontalVertical}>
94-
Main content
90+
<React.StrictMode>
91+
<Fixed style={{ outline: '1px solid black' }} height={400}>
92+
<LeftResizable style={{ borderRight: '1px dashed black' }} size="25%" centerContent={CenterType.HorizontalVertical}>
93+
Sidebar
94+
</LeftResizable>
95+
<Fill>
96+
<Fill centerContent={CenterType.HorizontalVertical}>
97+
Main content
98+
</Fill>
99+
<BottomResizable style={{ borderTop: '1px dashed black' }} size={100} centerContent={CenterType.HorizontalVertical}>
100+
Bottom area
101+
</BottomResizable>
95102
</Fill>
96-
<BottomResizable style={{ borderTop: '1px dashed black' }} size={100} centerContent={CenterType.HorizontalVertical}>
97-
Bottom area
98-
</BottomResizable>
99-
</Fill>
100-
</Fixed>
103+
</Fixed>
104+
</React.StrictMode>
101105

102106
We can add further nested spaces to add elements like title bars into different areas.
103107

@@ -136,28 +140,30 @@ const App = () => (
136140

137141
Now we have something like below:
138142

139-
<Fixed style={{ outline: '1px solid black' }} height={400}>
140-
<Top style={{ borderBottom: '1px dashed black', padding: 5 }} order={1} size={25} centerContent={CenterType.Vertical}>
141-
Title
142-
</Top>
143-
<Top style={{ borderBottom: '1px dashed black', padding: 5 }} order={2} size={25} centerContent={CenterType.Vertical}>
144-
Menu bar
145-
</Top>
146-
<Fill>
147-
<LeftResizable style={{ borderRight: '1px dashed black' }} size="25%">
148-
<Top style={{ borderBottom: '1px dashed black', padding: 5 }} size={25} centerContent={CenterType.Vertical}>Sidebar title</Top>
149-
<Fill centerContent={CenterType.HorizontalVertical}>Sidebar</Fill>
150-
</LeftResizable>
143+
<React.StrictMode>
144+
<Fixed style={{ outline: '1px solid black' }} height={400}>
145+
<Top style={{ borderBottom: '1px dashed black', padding: 5 }} order={1} size={25} centerContent={CenterType.Vertical}>
146+
Title
147+
</Top>
148+
<Top style={{ borderBottom: '1px dashed black', padding: 5 }} order={2} size={25} centerContent={CenterType.Vertical}>
149+
Menu bar
150+
</Top>
151151
<Fill>
152-
<Fill centerContent={CenterType.HorizontalVertical}>
153-
Main content
152+
<LeftResizable style={{ borderRight: '1px dashed black' }} size="25%">
153+
<Top style={{ borderBottom: '1px dashed black', padding: 5 }} size={25} centerContent={CenterType.Vertical}>Sidebar title</Top>
154+
<Fill centerContent={CenterType.HorizontalVertical}>Sidebar</Fill>
155+
</LeftResizable>
156+
<Fill>
157+
<Fill centerContent={CenterType.HorizontalVertical}>
158+
Main content
159+
</Fill>
160+
<BottomResizable style={{ borderTop: '1px dashed black' }} size={100} centerContent={CenterType.HorizontalVertical}>
161+
Bottom area
162+
</BottomResizable>
154163
</Fill>
155-
<BottomResizable style={{ borderTop: '1px dashed black' }} size={100} centerContent={CenterType.HorizontalVertical}>
156-
Bottom area
157-
</BottomResizable>
158164
</Fill>
159-
</Fill>
160-
</Fixed>
165+
</Fixed>
166+
</React.StrictMode>
161167

162168
### Introducing simple interactivity
163169

src/components/stories/Utils.tsx

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as React from "react";
22
import { CSSProperties } from "react";
3+
import { shortuuid } from "../../core-utils";
34
import {
45
Info,
56
Fixed,
@@ -164,39 +165,41 @@ export const DemoUI = () => {
164165
const [sidebarExpanded, setSidebarExpanded] = React.useState(true);
165166

166167
return (
167-
<Fixed style={{ outline: "1px solid black" }} height={400}>
168-
<Top style={{ borderBottom: "1px dashed black", padding: 5 }} order={1} size={25} centerContent={CenterType.Vertical}>
169-
Title
170-
</Top>
171-
<Top style={{ borderBottom: "1px dashed black", padding: 5 }} order={2} size={25} centerContent={CenterType.Vertical}>
172-
Menu bar
173-
</Top>
174-
<Fill>
175-
<LeftResizable style={{ borderRight: "1px dashed black", transition: "width 0.5s ease" }} size={sidebarExpanded ? 200 : 25}>
176-
<Top style={{ borderBottom: "1px dashed black" }} size={25}>
177-
{sidebarExpanded && (
178-
<Fill style={{ padding: 5 }} centerContent={CenterType.Vertical}>
179-
Sidebar title
180-
</Fill>
181-
)}
182-
<Right
183-
style={{ borderLeft: "1px dashed black", backgroundColor: "yellow", cursor: "pointer" }}
184-
size={25}
185-
onClick={() => setSidebarExpanded((prev) => !prev)}
186-
centerContent={CenterType.HorizontalVertical}>
187-
<i className={"fa fa-arrow-" + (sidebarExpanded ? "left" : "right")} />
188-
</Right>
189-
</Top>
190-
{sidebarExpanded && <Fill centerContent={CenterType.HorizontalVertical}>Sidebar</Fill>}
191-
</LeftResizable>
192-
<Fill style={{ borderRight: "1px dashed black", transition: "left 0.5s ease" }}>
193-
<Fill centerContent={CenterType.HorizontalVertical}>Main content</Fill>
194-
<BottomResizable style={{ borderTop: "1px dashed black" }} size={100} centerContent={CenterType.HorizontalVertical}>
195-
Bottom area
196-
</BottomResizable>
168+
<React.StrictMode>
169+
<Fixed style={{ outline: "1px solid black" }} height={400}>
170+
<Top style={{ borderBottom: "1px dashed black", padding: 5 }} order={1} size={25} centerContent={CenterType.Vertical}>
171+
Title
172+
</Top>
173+
<Top style={{ borderBottom: "1px dashed black", padding: 5 }} order={2} size={25} centerContent={CenterType.Vertical}>
174+
Menu bar
175+
</Top>
176+
<Fill>
177+
<LeftResizable style={{ borderRight: "1px dashed black", transition: "width 0.5s ease" }} size={sidebarExpanded ? 200 : 25}>
178+
<Top style={{ borderBottom: "1px dashed black" }} size={25}>
179+
{sidebarExpanded && (
180+
<Fill style={{ padding: 5 }} centerContent={CenterType.Vertical}>
181+
Sidebar title
182+
</Fill>
183+
)}
184+
<Right
185+
style={{ borderLeft: "1px dashed black", backgroundColor: "yellow", cursor: "pointer" }}
186+
size={25}
187+
onClick={() => setSidebarExpanded((prev) => !prev)}
188+
centerContent={CenterType.HorizontalVertical}>
189+
<i className={"fa fa-arrow-" + (sidebarExpanded ? "left" : "right")} />
190+
</Right>
191+
</Top>
192+
{sidebarExpanded && <Fill centerContent={CenterType.HorizontalVertical}>Sidebar</Fill>}
193+
</LeftResizable>
194+
<Fill style={{ borderRight: "1px dashed black", transition: "left 0.5s ease" }}>
195+
<Fill centerContent={CenterType.HorizontalVertical}>Main content</Fill>
196+
<BottomResizable style={{ borderTop: "1px dashed black" }} size={100} centerContent={CenterType.HorizontalVertical}>
197+
Bottom area
198+
</BottomResizable>
199+
</Fill>
197200
</Fill>
198-
</Fill>
199-
</Fixed>
201+
</Fixed>
202+
</React.StrictMode>
200203
);
201204
};
202205

src/core-react.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import * as PropTypes from "prop-types";
99
export const ParentContext = React.createContext<string | undefined>(undefined);
1010
export const DOMRectContext = React.createContext<DOMRect | undefined>(undefined);
1111
export const LayerContext = React.createContext<number | undefined>(undefined);
12+
export const OptionsContext = React.createContext<IReactSpacesOptions>({});
1213
export const currentStore = createStore();
1314

1415
export const commonProps = {
@@ -30,6 +31,10 @@ export const commonProps = {
3031
onTouchEnd: PropTypes.func,
3132
};
3233

34+
export interface IReactSpacesOptions {
35+
debug?: boolean
36+
}
37+
3338
export interface IReactEvents {
3439
onClick?: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
3540
onDoubleClick?: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
@@ -55,17 +60,22 @@ export function useSpace(props: ISpaceProps) {
5560
const update = useForceUpdate();
5661
const parent = React.useContext(ParentContext);
5762
const layer = React.useContext(LayerContext);
58-
const spaceId = React.useRef(props.id || `s${shortuuid()}`);
63+
const { debug } = React.useContext(OptionsContext);
64+
const [spaceId] = React.useState(props.id || `s${shortuuid()}`);
5965
const elementRef = React.useRef<HTMLElement>();
6066
const resizeSensor = React.useRef<ResizeSensor>();
6167
const [domRect, setDomRect] = React.useState<DOMRect>();
6268

63-
let space = store.getSpace(spaceId.current)!;
69+
let space = store.getSpace(spaceId)!;
70+
71+
if (debug) {
72+
console.table(store.getSpaces());
73+
}
6474

6575
const parsedProps = {
6676
...props,
6777
...{
68-
id: spaceId.current,
78+
id: spaceId,
6979
zIndex: coalesce(props.zIndex, layer),
7080
},
7181
};

src/core-resizing.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { SyntheticEvent } from "react";
2-
import ReactDOM from "react-dom";
32
import { ISpaceDefinition, ISize, ResizeType, Orientation, ISpaceStore } from "./core-types";
43
import { throttle, coalesce } from "./core-utils";
54

0 commit comments

Comments
 (0)