@khanacademy/wonder-blocks-core 4.1.0 → 4.2.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,11 +1,18 @@
1
1
  # @khanacademy/wonder-blocks-core
2
2
 
3
+ ## 4.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 0aed8723: Adds `throwIfNested` required prop to `RenderStateRoot`.
8
+
3
9
  ## 4.1.0
10
+
4
11
  ### Minor Changes
5
12
 
6
- - 45588e5f: Fix an issue with `useUniqueIdWithMock`/`useUniqueIdWithoutMock`
7
- rerender more than was needed. The fix introduces `<RenderStateRoot>`
8
- which must be an ancestor to all components uses these hooks.
9
- - 875b7893: Nesting of `RenderStateRoot`s inside each other can result in extra renders
10
- and potentially incorrect behavior. `RenderStateRoot` now throws if it
11
- appears as a descendent of another `RenderStateRoot`.
13
+ - 45588e5f: Fix an issue with `useUniqueIdWithMock`/`useUniqueIdWithoutMock`
14
+ rerender more than was needed. The fix introduces `<RenderStateRoot>`
15
+ which must be an ancestor to all components uses these hooks.
16
+ - 875b7893: Nesting of `RenderStateRoot`s inside each other can result in extra renders
17
+ and potentially incorrect behavior. `RenderStateRoot` now throws if it
18
+ appears as a descendent of another `RenderStateRoot`.
package/dist/es/index.js CHANGED
@@ -688,23 +688,32 @@ const {
688
688
  useState
689
689
  } = React;
690
690
  const RenderStateRoot = ({
691
- children
691
+ children,
692
+ throwIfNested
692
693
  }) => {
693
694
  const [firstRender, setFirstRender] = useState(true);
694
695
  const contextValue = useContext(RenderStateContext);
695
-
696
- if (contextValue !== RenderState.Root) {
697
- throw new Error("There's already a <RenderStateRoot> above this instance in " + "the render tree. This instance should be removed.");
698
- }
699
-
700
696
  useEffect(() => {
701
697
  setFirstRender(false);
702
698
  }, []); // This effect will only run once.
703
699
 
700
+ if (contextValue !== RenderState.Root) {
701
+ if (throwIfNested) {
702
+ throw new Error("There's already a <RenderStateRoot> above this instance in " + "the render tree. This instance should be removed.");
703
+ } // Avoid rendering multiple providers if this RenderStateRoot
704
+ // is nested inside another one.
705
+
706
+
707
+ return children;
708
+ }
709
+
704
710
  const value = firstRender ? RenderState.Initial : RenderState.Standard;
705
711
  return /*#__PURE__*/React.createElement(RenderStateContext.Provider, {
706
712
  value: value
707
713
  }, children);
708
714
  };
715
+ RenderStateRoot.defaultProps = {
716
+ throwIfNested: true
717
+ };
709
718
 
710
719
  export { IDProvider, RenderStateRoot, server as Server, Text, UniqueIDProvider, View, WithSSRPlaceholder, addStyle, useUniqueIdWithMock, useUniqueIdWithoutMock };
package/dist/index.js CHANGED
@@ -934,24 +934,33 @@ const {
934
934
  useState
935
935
  } = react__WEBPACK_IMPORTED_MODULE_0__;
936
936
  const RenderStateRoot = ({
937
- children
937
+ children,
938
+ throwIfNested
938
939
  }) => {
939
940
  const [firstRender, setFirstRender] = useState(true);
940
941
  const contextValue = useContext(_render_state_context_js__WEBPACK_IMPORTED_MODULE_1__[/* RenderStateContext */ "b"]);
941
-
942
- if (contextValue !== _render_state_context_js__WEBPACK_IMPORTED_MODULE_1__[/* RenderState */ "a"].Root) {
943
- throw new Error("There's already a <RenderStateRoot> above this instance in " + "the render tree. This instance should be removed.");
944
- }
945
-
946
942
  useEffect(() => {
947
943
  setFirstRender(false);
948
944
  }, []); // This effect will only run once.
949
945
 
946
+ if (contextValue !== _render_state_context_js__WEBPACK_IMPORTED_MODULE_1__[/* RenderState */ "a"].Root) {
947
+ if (throwIfNested) {
948
+ throw new Error("There's already a <RenderStateRoot> above this instance in " + "the render tree. This instance should be removed.");
949
+ } // Avoid rendering multiple providers if this RenderStateRoot
950
+ // is nested inside another one.
951
+
952
+
953
+ return children;
954
+ }
955
+
950
956
  const value = firstRender ? _render_state_context_js__WEBPACK_IMPORTED_MODULE_1__[/* RenderState */ "a"].Initial : _render_state_context_js__WEBPACK_IMPORTED_MODULE_1__[/* RenderState */ "a"].Standard;
951
957
  return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_render_state_context_js__WEBPACK_IMPORTED_MODULE_1__[/* RenderStateContext */ "b"].Provider, {
952
958
  value: value
953
959
  }, children);
954
960
  };
961
+ RenderStateRoot.defaultProps = {
962
+ throwIfNested: true
963
+ };
955
964
 
956
965
  /***/ }),
957
966
  /* 15 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-core",
3
- "version": "4.1.0",
3
+ "version": "4.2.0",
4
4
  "design": "v1",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -56,7 +56,7 @@ describe("RenderStateRoot", () => {
56
56
  expect(values[1]).toEqual(RenderState.Standard);
57
57
  });
58
58
 
59
- it("should not allow nesting of <RenderStateRoot>", () => {
59
+ it("should not allow nesting of <RenderStateRoot> when", () => {
60
60
  // Act
61
61
  const underTest = () =>
62
62
  render(
@@ -69,4 +69,23 @@ describe("RenderStateRoot", () => {
69
69
  `"There's already a <RenderStateRoot> above this instance in the render tree. This instance should be removed."`,
70
70
  );
71
71
  });
72
+
73
+ it("should allow nesting of <RenderStateRoot> when throwIfNested={false}", () => {
74
+ // Act
75
+ const underTest = () =>
76
+ render(
77
+ <RenderStateRoot throwIfNested={false}>
78
+ <RenderStateRoot throwIfNested={false}>
79
+ Hello, world!
80
+ </RenderStateRoot>
81
+ </RenderStateRoot>,
82
+ );
83
+
84
+ expect(underTest).not.toThrowError();
85
+ });
86
+
87
+ // This test can be written once ADR #526 has been implemented. I've left
88
+ // a comment in the ADR about this kind of test case being something we
89
+ // should support.
90
+ it.todo("should only render a single context provider when nesting");
72
91
  });
@@ -11,23 +11,35 @@ const {useContext, useEffect, useState} = React;
11
11
 
12
12
  type Props = {|
13
13
  children: React.Node,
14
+
15
+ /**
16
+ * Whether the component should throw when nested. Defaults to `true`.
17
+ */
18
+ throwIfNested?: boolean,
14
19
  |};
15
20
 
16
- export const RenderStateRoot = ({children}: Props): React.Node => {
21
+ export const RenderStateRoot = ({
22
+ children,
23
+ throwIfNested,
24
+ }: Props): React.Node => {
17
25
  const [firstRender, setFirstRender] = useState<boolean>(true);
18
26
  const contextValue = useContext(RenderStateContext);
19
-
20
- if (contextValue !== RenderState.Root) {
21
- throw new Error(
22
- "There's already a <RenderStateRoot> above this instance in " +
23
- "the render tree. This instance should be removed.",
24
- );
25
- }
26
-
27
27
  useEffect(() => {
28
28
  setFirstRender(false);
29
29
  }, []); // This effect will only run once.
30
30
 
31
+ if (contextValue !== RenderState.Root) {
32
+ if (throwIfNested) {
33
+ throw new Error(
34
+ "There's already a <RenderStateRoot> above this instance in " +
35
+ "the render tree. This instance should be removed.",
36
+ );
37
+ }
38
+ // Avoid rendering multiple providers if this RenderStateRoot
39
+ // is nested inside another one.
40
+ return children;
41
+ }
42
+
31
43
  const value = firstRender ? RenderState.Initial : RenderState.Standard;
32
44
 
33
45
  return (
@@ -36,3 +48,7 @@ export const RenderStateRoot = ({children}: Props): React.Node => {
36
48
  </RenderStateContext.Provider>
37
49
  );
38
50
  };
51
+
52
+ RenderStateRoot.defaultProps = {
53
+ throwIfNested: true,
54
+ };