diff --git a/lib/Reactify.re b/lib/Reactify.re index 37342f3..3feef9e 100644 --- a/lib/Reactify.re +++ b/lib/Reactify.re @@ -518,6 +518,7 @@ module Make = (ReconcilerImpl: Reconciler) => { }; module State = State; +module Effects = Effects; module Event = Event; module Utility = Utility; -module Object = Object; \ No newline at end of file +module Object = Object; diff --git a/lib/Reactify.rei b/lib/Reactify.rei index e9af404..18a3329 100644 --- a/lib/Reactify.rei +++ b/lib/Reactify.rei @@ -7,6 +7,7 @@ module Make: type node = ReconcilerImpl.node and type primitives = ReconcilerImpl.primitives; +module Effects = Effects; module State = State; module Event = Event; module Utility = Utility; diff --git a/test/HooksUseStateTest.re b/test/HooksUseStateTest.re index 2fd154b..6b43cc9 100644 --- a/test/HooksUseStateTest.re +++ b/test/HooksUseStateTest.re @@ -5,6 +5,8 @@ open TestReconciler; open TestUtility; module Event = Reactify.Event; +module Effects = Reactify.Effects; + /* Use our Reconciler to create our own instance */ module TestReact = Reactify.Make(TestReconciler); @@ -51,19 +53,19 @@ test("useState", () => { }); module ComponentThatUpdatesState = ( - val component((render, ~children, ~event: Event.t(int), ()) => + val component((render, ~condition=Effects.Always, ~children, ~event: Event.t(int), ()) => render( () => { /* Hooks */ let (s, setS) = useState(2); /* End hooks */ - useEffect(() => { + useEffect(~condition, () => { let unsubscribe = Event.subscribe(event, v => setS(v)); () => unsubscribe(); }); - ; + ; }, ~children, ) @@ -157,13 +159,13 @@ test("useState", () => { }); module ComponentThatUpdatesStateAndRendersChildren = ( - val component((render, ~children, ~event: Event.t(int), ()) => + val component((render, ~condition=Effects.Always, ~children, ~event: Event.t(int), ()) => render( () => { /* Hooks */ let (s, setS) = useState(2); - useEffect(() => { + useEffect(~condition, () => { let unsubscribe = Event.subscribe(event, v => setS(v)); () => unsubscribe(); }); @@ -176,7 +178,7 @@ test("useState", () => { ) ); - test("nested state works as expected", () => { + test("nested state works", () => { let rootNode = createRootNode(); let container = createContainer(rootNode); @@ -210,6 +212,40 @@ test("useState", () => { validateStructure(rootNode, expectedStructure); }); + test("regression test: nested state w/ long-lived handle to setState", () => { + let rootNode = createRootNode(); + let container = createContainer(rootNode); + + let outerEvent = Event.create(); + let innerEvent = Event.create(); + + updateContainer( + container, + + + , + ); + + let expectedStructure: tree(primitives) = + TreeNode(Root, [TreeNode(A(2), [TreeLeaf(A(2))])]); + validateStructure(rootNode, expectedStructure); + + Event.dispatch(outerEvent, 5); + let expectedStructure: tree(primitives) = + TreeNode(Root, [TreeNode(A(5), [TreeLeaf(A(2))])]); + validateStructure(rootNode, expectedStructure); + + Event.dispatch(innerEvent, 6); + let expectedStructure: tree(primitives) = + TreeNode(Root, [TreeNode(A(5), [TreeLeaf(A(6))])]); + validateStructure(rootNode, expectedStructure); + + Event.dispatch(outerEvent, 7); + let expectedStructure: tree(primitives) = + TreeNode(Root, [TreeNode(A(7), [TreeLeaf(A(6))])]); + validateStructure(rootNode, expectedStructure); + }); + module ComponentThatWrapsEitherPrimitiveOrComponent = ( val component((render, ~children, ~event: Event.t(renderOption), ()) => render( diff --git a/test/StateTest.ts b/test/StateTest.ts deleted file mode 100644 index eb93dca..0000000 --- a/test/StateTest.ts +++ /dev/null @@ -1,28 +0,0 @@ -module State = Reactify.State; - -test("Object conversion works with ints", () => { - let i = 1; - let stateI = Object.to_object(i); - let rehydratedI = Object.of_object(stateI); - assert(i == rehydratedI); -}); - -test("Object conversion works with tuples", () => { - let p = (1, "a"); - let stateP = Object.to_object(p); - let rehydratedP = Object.of_object(stateP); - assert(p == rehydratedP); -}); - -test("Object can be used to create list of different types", () => { - let stateList: list(State.t) = []; - - let stateList = [Object.to_object(1), ...stateList]; - let stateList = [Object.to_object(("a", "b")), ...stateList]; - - let firstElement = List.nth(stateList, 0); - assert(Object.of_object(firstElement) == ("a", "b")); - - let lastElement = List.nth(stateList, 1); - assert(Object.of_object(lastElement) == 1); -});