Skip to content

Commit c70608e

Browse files
authored
Merge pull request #120 from aeagle/feature/react-18
Upgrade dev dependencies to React 18 and applied fix for React 18 strict mode
2 parents 8b3c9ab + 72c20e6 commit c70608e

File tree

10 files changed

+6280
-6994
lines changed

10 files changed

+6280
-6994
lines changed

.storybook/main.js

+4-6
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,13 @@ module.exports = {
66
"@storybook/addon-actions",
77
"@storybook/addon-links",
88
{
9-
name: "@storybook/addon-docs/preset",
9+
name: "@storybook/addon-docs",
1010
options: {
1111
configureJSX: true,
1212
inlineStories: false,
1313
},
1414
},
1515
],
16-
typescript: {
17-
check: true,
18-
checkOptions: {},
19-
reactDocgen: "react-docgen-typescript",
20-
},
2116
webpackFinal: async (config, { configType }) => {
2217
if (process.env.NODE === "production") {
2318
config.output.publicPath = "/react-spaces/docs";
@@ -31,4 +26,7 @@ module.exports = {
3126

3227
return config;
3328
},
29+
reactOptions: {
30+
strictMode: true,
31+
},
3432
};

package-lock.json

+6,178-6,961
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+13-13
Original file line numberDiff line numberDiff line change
@@ -32,22 +32,22 @@
3232
},
3333
"devDependencies": {
3434
"@babel/core": "^7.5.5",
35-
"@rollup/plugin-commonjs": "^21.0.1",
3635
"@rollup/plugin-babel": "^5.3.0",
36+
"@rollup/plugin-commonjs": "^21.0.1",
3737
"@rollup/plugin-node-resolve": "^13.0.6",
38-
"@storybook/addon-actions": "^6.3.12",
39-
"@storybook/addon-docs": "^6.3.12",
38+
"@storybook/addon-actions": "^6.5.5",
39+
"@storybook/addon-docs": "^6.5.5",
4040
"@storybook/addon-knobs": "^6.3.1",
41-
"@storybook/addon-links": "^6.3.12",
42-
"@storybook/addons": "^6.3.12",
43-
"@storybook/react": "^6.3.12",
41+
"@storybook/addon-links": "^6.5.5",
42+
"@storybook/addons": "^6.5.5",
43+
"@storybook/react": "^6.5.5",
4444
"@testing-library/jest-dom": "^5.15.0",
4545
"@testing-library/react": "^12.1.2",
4646
"@types/jest": "^24.0.15",
4747
"@types/node": "^12.6.8",
4848
"@types/prop-types": "^15.7.3",
49-
"@types/react": "^16.8.23",
50-
"@types/react-dom": "^16.8.4",
49+
"@types/react": "^18.0.9",
50+
"@types/react-dom": "^18.0.5",
5151
"acorn": "^7.1.1",
5252
"awesome-typescript-loader": "^5.2.1",
5353
"babel-loader": "^8.0.6",
@@ -56,18 +56,18 @@
5656
"is-svg": "^4.2.2",
5757
"jest": "^25.4.0",
5858
"jest-expect-message": "^1.0.2",
59-
"node-sass": "^7.0.0",
6059
"prettier": "^1.19.1",
61-
"react": "^17.0.2",
60+
"react": "^18.1.0",
6261
"react-docgen-typescript-loader": "^3.7.0",
63-
"react-dom": "^17.0.2",
62+
"react-dom": "^18.1.0",
6463
"rollup": "^2.60.0",
6564
"rollup-plugin-fork-ts-checker": "0.0.6",
6665
"rollup-plugin-postcss": "^3.1.8",
6766
"rollup-plugin-sourcemaps": "^0.6.3",
6867
"rollup-plugin-typescript2": "^0.31.0",
6968
"rollup-plugin-uglify": "^6.0.4",
7069
"rollup-watch": "^4.3.1",
70+
"sass": "^1.52.1",
7171
"sass-loader": "^8.0.2",
7272
"ts-jest": "^25.4.0",
7373
"ts-loader": "^6.2.1",
@@ -78,8 +78,8 @@
7878
"cssstyle": "2.3.0"
7979
},
8080
"peerDependencies": {
81-
"react": "^16.8.0 || ^17",
82-
"react-dom": "^16.8.0 || ^17"
81+
"react": "^16.8.0 || ^17 || ^18",
82+
"react-dom": "^16.8.0 || ^17 || ^18"
8383
},
8484
"scripts": {
8585
"start": "rollup -c -w",

src/components/Centered.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
import * as React from "react";
22

3-
export const Centered: React.FC = (props) => <div className={`spaces-centered`}>{props.children}</div>;
3+
interface IProps {
4+
children?: React.ReactNode;
5+
}
6+
7+
export const Centered: React.FC<IProps> = (props) => <div className={`spaces-centered`}>{props.children}</div>;

src/components/CenteredVertically.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
import * as React from "react";
22

3-
export const CenteredVertically: React.FC = (props) => <div className={`spaces-centered-vertically`}>{props.children}</div>;
3+
interface IProps {
4+
children?: React.ReactNode;
5+
}
6+
7+
export const CenteredVertically: React.FC<IProps> = (props) => <div className={`spaces-centered-vertically`}>{props.children}</div>;

src/components/Layer.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ import * as React from "react";
22
import { LayerContext } from "../core-react";
33
import * as PropTypes from "prop-types";
44

5-
export const Layer: React.FC<{ zIndex: number }> = (props) => <LayerContext.Provider value={props.zIndex}>{props.children}</LayerContext.Provider>;
5+
interface IProps {
6+
zIndex: number;
7+
children?: React.ReactNode;
8+
}
9+
10+
export const Layer: React.FC<IProps> = (props) => <LayerContext.Provider value={props.zIndex}>{props.children}</LayerContext.Provider>;
611

712
Layer.propTypes = {
813
zIndex: PropTypes.number.isRequired,

src/components/Options.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import * as React from "react";
22
import { IReactSpacesOptions, OptionsContext } from "../core-react";
33

4-
export const Options: React.FC<IReactSpacesOptions> = ({ children, ...opts }) => {
4+
interface IProps extends IReactSpacesOptions {
5+
children?: React.ReactNode;
6+
}
7+
8+
export const Options: React.FC<IProps> = ({ children, ...opts }) => {
59
return <OptionsContext.Provider value={opts}>{children}</OptionsContext.Provider>;
610
};

src/components/Space.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { CenterType, ResizeHandlePlacement, AnchorType, Type } from "../core-types";
2-
import { useSpace, ParentContext, LayerContext, DOMRectContext, IReactSpaceInnerProps } from "../core-react";
2+
import { useSpace, ParentContext, LayerContext, DOMRectContext, IReactSpaceInnerProps, useEffectOnce } from "../core-react";
33
import * as React from "react";
44
import { Centered } from "./Centered";
55
import { CenteredVertically } from "./CenteredVertically";
@@ -59,9 +59,9 @@ const SpaceInner: React.FC<IReactSpaceInnerProps & { wrapperInstance: Space }> =
5959
...{ id: props.id || props.wrapperInstance["_react_spaces_uniqueid"] },
6060
});
6161

62-
React.useEffect(() => {
62+
useEffectOnce(() => {
6363
space.element = elementRef.current!;
64-
}, []);
64+
});
6565

6666
const userClasses = className ? className.split(" ").map((c) => c.trim()) : [];
6767

src/components/stories/Utils.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const CommonHeader = () => (
2323
</div>
2424
);
2525

26-
export const PropsTable: React.FC = (props) => (
26+
export const PropsTable: React.FC<{ children?: React.ReactNode }> = (props) => (
2727
<table className="sbdocs sbdocs-table properties-table css-lckf62">
2828
<tbody>
2929
<tr>
@@ -47,7 +47,7 @@ const propHeaderStyle: CSSProperties = {
4747
fontWeight: 500,
4848
};
4949

50-
export const PropsHeader: React.FC = (props) => (
50+
export const PropsHeader: React.FC<{ children?: React.ReactNode }> = (props) => (
5151
<tr>
5252
<td colSpan={4} style={propHeaderStyle}>
5353
{props.children}

src/core-react.ts

+59-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,56 @@
11
import * as React from "react";
22
import { createStore } from "./core";
3-
import { ISpaceProps, ISpaceStore, ISpaceDefinition, ResizeType, CenterType, ISpaceContext, ICommonProps } from "./core-types";
3+
import {
4+
ISpaceProps,
5+
ISpaceStore,
6+
ISpaceDefinition,
7+
ResizeType,
8+
CenterType,
9+
ISpaceContext,
10+
ICommonProps,
11+
ResizeMouseEvent,
12+
OnDragEnd,
13+
ResizeTouchEvent,
14+
} from "./core-types";
415
import { coalesce, shortuuid } from "./core-utils";
516
import { ResizeSensor } from "css-element-queries";
617
import * as PropTypes from "prop-types";
18+
import { useEffect, useRef, useState } from "react";
19+
20+
// WORKAROUND for React18 strict mode
21+
// https://blog.ag-grid.com/avoiding-react-18-double-mount/
22+
export const useEffectOnce = (effect: () => void | (() => void)) => {
23+
const destroyFunc = useRef<void | (() => void)>();
24+
const effectCalled = useRef(false);
25+
const renderAfterCalled = useRef(false);
26+
const [_val, setVal] = useState<number>(0);
27+
28+
if (effectCalled.current) {
29+
renderAfterCalled.current = true;
30+
}
31+
32+
useEffect(() => {
33+
// only execute the effect first time around
34+
if (!effectCalled.current) {
35+
destroyFunc.current = effect();
36+
effectCalled.current = true;
37+
}
38+
39+
// this forces one render after the effect is run
40+
setVal((val) => val + 1);
41+
42+
return () => {
43+
// if the comp didn't render since the useEffect was called,
44+
// we know it's the dummy React cycle
45+
if (!renderAfterCalled.current) {
46+
return;
47+
}
48+
if (destroyFunc.current) {
49+
destroyFunc.current();
50+
}
51+
};
52+
}, []);
53+
};
754

855
export const ParentContext = React.createContext<string | undefined>(undefined);
956
export const DOMRectContext = React.createContext<DOMRect | undefined>(undefined);
@@ -52,6 +99,7 @@ export interface IReactEvents {
5299
export interface IReactSpaceCommonProps extends ICommonProps, IReactEvents {
53100
style?: React.CSSProperties;
54101
as?: keyof React.ReactDOM | React.ComponentType<ICommonProps>;
102+
children?: React.ReactNode;
55103
}
56104

57105
export interface IReactSpaceInnerProps extends IReactSpaceCommonProps, ISpaceProps, IReactEvents {
@@ -104,7 +152,7 @@ export function useSpace(props: IReactSpaceInnerProps) {
104152

105153
const resizeHandles = useSpaceResizeHandles(store, space);
106154

107-
React.useEffect(() => {
155+
useEffectOnce(() => {
108156
const rect = elementRef.current!.getBoundingClientRect() as DOMRect;
109157
space!.dimension = {
110158
...rect,
@@ -138,7 +186,7 @@ export function useSpace(props: IReactSpaceInnerProps) {
138186
resizeSensor.current && resizeSensor.current.detach();
139187
store.removeSpace(space!);
140188
};
141-
}, []);
189+
});
142190

143191
return { space: space, resizeHandles: resizeHandles, domRect: domRect, elementRef: elementRef };
144192
}
@@ -207,8 +255,14 @@ export function useCurrentSpace() {
207255

208256
const domRect = React.useContext(DOMRectContext);
209257
const layer = React.useContext(LayerContext);
210-
const onMouseDrag = React.useCallback((e, onDragEnd) => (space ? store.startMouseDrag(space, e, onDragEnd) : null), [spaceId]);
211-
const onTouchDrag = React.useCallback((e, onDragEnd) => (space ? store.startTouchDrag(space, e, onDragEnd) : null), [spaceId]);
258+
const onMouseDrag = React.useCallback(
259+
(e: ResizeMouseEvent, onDragEnd: OnDragEnd | undefined) => (space ? store.startMouseDrag(space, e, onDragEnd) : null),
260+
[spaceId],
261+
);
262+
const onTouchDrag = React.useCallback(
263+
(e: ResizeTouchEvent, onDragEnd: OnDragEnd | undefined) => (space ? store.startTouchDrag(space, e, onDragEnd) : null),
264+
[spaceId],
265+
);
212266
const onForceUpdate = React.useCallback(() => (space ? store.updateStyles(space) : null), [spaceId]);
213267

214268
const defaults = { width: 0, height: 0, x: 0, y: 0 };

0 commit comments

Comments
 (0)