@headless-tree/react 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # @headless-tree/react
2
2
 
3
+ ## 1.4.0
4
+
3
5
  ## 1.3.0
4
6
 
5
7
  ### Patch Changes
package/dist/index.js CHANGED
@@ -123,7 +123,24 @@ var AssistiveTreeDescription = (_a) => {
123
123
  // src/use-tree.tsx
124
124
  var import_react2 = require("react");
125
125
  var import_core2 = require("@headless-tree/core");
126
+ var useApplyAfterMount = () => {
127
+ const isMounted = (0, import_react2.useRef)(false);
128
+ const callbacks = (0, import_react2.useRef)([]);
129
+ (0, import_react2.useEffect)(() => {
130
+ isMounted.current = true;
131
+ callbacks.current.forEach((callback) => callback());
132
+ }, []);
133
+ const apply = (callback) => {
134
+ if (isMounted.current) {
135
+ callback();
136
+ } else {
137
+ callbacks.current.push(callback);
138
+ }
139
+ };
140
+ return apply;
141
+ };
126
142
  var useTree = (config) => {
143
+ const apply = useApplyAfterMount();
127
144
  const [tree] = (0, import_react2.useState)(() => ({ current: (0, import_core2.createTree)(config) }));
128
145
  const [state, setState] = (0, import_react2.useState)(
129
146
  () => tree.current.getState()
@@ -131,16 +148,16 @@ var useTree = (config) => {
131
148
  (0, import_react2.useEffect)(() => {
132
149
  tree.current.rebuildTree();
133
150
  }, [tree]);
134
- (0, import_react2.useInsertionEffect)(() => {
135
- tree.current.setConfig((prev) => __spreadProps(__spreadValues(__spreadValues({}, prev), config), {
136
- state: __spreadValues(__spreadValues({}, state), config.state),
137
- setState: (state2) => {
151
+ tree.current.setConfig((prev) => __spreadProps(__spreadValues(__spreadValues({}, prev), config), {
152
+ state: __spreadValues(__spreadValues({}, state), config.state),
153
+ setState: (state2) => {
154
+ apply(() => {
138
155
  var _a;
139
156
  setState(state2);
140
157
  (_a = config.setState) == null ? void 0 : _a.call(config, state2);
141
- }
142
- }));
143
- });
158
+ });
159
+ }
160
+ }));
144
161
  return tree.current;
145
162
  };
146
163
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.mjs CHANGED
@@ -63,9 +63,26 @@ var AssistiveTreeDescription = (_a) => {
63
63
  };
64
64
 
65
65
  // src/use-tree.tsx
66
- import { useEffect, useInsertionEffect, useState } from "react";
66
+ import { useEffect, useRef, useState } from "react";
67
67
  import { createTree } from "@headless-tree/core";
68
+ var useApplyAfterMount = () => {
69
+ const isMounted = useRef(false);
70
+ const callbacks = useRef([]);
71
+ useEffect(() => {
72
+ isMounted.current = true;
73
+ callbacks.current.forEach((callback) => callback());
74
+ }, []);
75
+ const apply = (callback) => {
76
+ if (isMounted.current) {
77
+ callback();
78
+ } else {
79
+ callbacks.current.push(callback);
80
+ }
81
+ };
82
+ return apply;
83
+ };
68
84
  var useTree = (config) => {
85
+ const apply = useApplyAfterMount();
69
86
  const [tree] = useState(() => ({ current: createTree(config) }));
70
87
  const [state, setState] = useState(
71
88
  () => tree.current.getState()
@@ -73,16 +90,16 @@ var useTree = (config) => {
73
90
  useEffect(() => {
74
91
  tree.current.rebuildTree();
75
92
  }, [tree]);
76
- useInsertionEffect(() => {
77
- tree.current.setConfig((prev) => __spreadProps(__spreadValues(__spreadValues({}, prev), config), {
78
- state: __spreadValues(__spreadValues({}, state), config.state),
79
- setState: (state2) => {
93
+ tree.current.setConfig((prev) => __spreadProps(__spreadValues(__spreadValues({}, prev), config), {
94
+ state: __spreadValues(__spreadValues({}, state), config.state),
95
+ setState: (state2) => {
96
+ apply(() => {
80
97
  var _a;
81
98
  setState(state2);
82
99
  (_a = config.setState) == null ? void 0 : _a.call(config, state2);
83
- }
84
- }));
85
- });
100
+ });
101
+ }
102
+ }));
86
103
  return tree.current;
87
104
  };
88
105
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@headless-tree/react",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "main": "dist/index.d.ts",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.mts",
package/src/use-tree.tsx CHANGED
@@ -1,7 +1,34 @@
1
- import { useEffect, useInsertionEffect, useState } from "react";
1
+ import { useEffect, useRef, useState } from "react";
2
2
  import { TreeConfig, TreeState, createTree } from "@headless-tree/core";
3
3
 
4
+ /* A bug with NextJS was reported in the past where very quick state updates (i.e. data
5
+ * loader returning withing milliseconds) will cause the state update to occur before
6
+ * mount, resulting in a console warning. This alleviates this.
7
+ * We should monitor if this remains a problem in the future, maybe we can eventually
8
+ * remove this workaround...
9
+ */
10
+ const useApplyAfterMount = () => {
11
+ const isMounted = useRef(false);
12
+ const callbacks = useRef<(() => void)[]>([]);
13
+
14
+ useEffect(() => {
15
+ isMounted.current = true;
16
+ callbacks.current.forEach((callback) => callback());
17
+ }, []);
18
+
19
+ const apply = (callback: () => void) => {
20
+ if (isMounted.current) {
21
+ callback();
22
+ } else {
23
+ callbacks.current.push(callback);
24
+ }
25
+ };
26
+
27
+ return apply;
28
+ };
29
+
4
30
  export const useTree = <T,>(config: TreeConfig<T>) => {
31
+ const apply = useApplyAfterMount();
5
32
  const [tree] = useState(() => ({ current: createTree(config) }));
6
33
  const [state, setState] = useState<Partial<TreeState<T>>>(() =>
7
34
  tree.current.getState(),
@@ -11,21 +38,20 @@ export const useTree = <T,>(config: TreeConfig<T>) => {
11
38
  tree.current.rebuildTree();
12
39
  }, [tree]); // runs only once after mount
13
40
 
14
- useInsertionEffect(() => {
15
- tree.current.setConfig((prev) => ({
16
- ...prev,
17
- ...config,
18
- state: {
19
- // ...prev.state,
20
- ...state,
21
- ...config.state,
22
- },
23
- setState: (state) => {
41
+ tree.current.setConfig((prev) => ({
42
+ ...prev,
43
+ ...config,
44
+ state: {
45
+ ...state,
46
+ ...config.state,
47
+ },
48
+ setState: (state) => {
49
+ apply(() => {
24
50
  setState(state);
25
51
  config.setState?.(state);
26
- },
27
- }));
28
- });
52
+ });
53
+ },
54
+ }));
29
55
 
30
56
  return tree.current;
31
57
  };