From 961a4bbd1dbb51e27acdf828c9ca2a2b3857e127 Mon Sep 17 00:00:00 2001 From: Amber's Careware <93293456+ambers-careware@users.noreply.github.com> Date: Wed, 17 Nov 2021 12:46:45 -0700 Subject: [PATCH 01/13] Create createTyped This utility allows type safety for components that is more compatible with luau's bidirectional typings (using type assertions manually causes problems!) --- Pract/createTyped | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 Pract/createTyped diff --git a/Pract/createTyped b/Pract/createTyped new file mode 100644 index 0000000..c8d498c --- /dev/null +++ b/Pract/createTyped @@ -0,0 +1,9 @@ +--!strict + +local Types = require(script.Parent.Types) + +local createTyped: (component: (PropsType) -> Types.Element, props: PropsType) = function(component, props) + return component(props) +end + +return createTyped From 80a502a38ede4f4873ec2f256543d09c6987c301 Mon Sep 17 00:00:00 2001 From: Amber's Careware <93293456+ambers-careware@users.noreply.github.com> Date: Wed, 17 Nov 2021 12:47:15 -0700 Subject: [PATCH 02/13] Update init.lua --- Pract/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/Pract/init.lua b/Pract/init.lua index 01de0af..d4c36ba 100644 --- a/Pract/init.lua +++ b/Pract/init.lua @@ -25,6 +25,7 @@ export type Lifecycle = Types.Lifecycle -- Base element functions Pract.create = require(script.create) +Pract.createTyped = require(script.createTyped) Pract.index = require(script.index) Pract.stamp = require(script.stamp) Pract.decorate = require(script.decorate) From 9f7d935524fe16214f0411ce44e61878733b6aa3 Mon Sep 17 00:00:00 2001 From: Amber's Careware <93293456+ambers-careware@users.noreply.github.com> Date: Wed, 17 Nov 2021 12:48:20 -0700 Subject: [PATCH 03/13] Update Types.lua Add generic ComponentTyped that allows components to have more typesafe types. --- Pract/Types.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Pract/Types.lua b/Pract/Types.lua index 33c6dff..5b9979b 100644 --- a/Pract/Types.lua +++ b/Pract/Types.lua @@ -16,6 +16,7 @@ export type Element = { [any]: any, } export type Component = (props: any) -> Element +export type ComponentTyped = (props: PropsType) -> Element --export type ComponentTyped

= (props: P) -> any export type ClassState = {[string]: any} export type ClassStateUpdateThunk = (state: ClassState, props: PropsArgument) -> ClassState @@ -97,4 +98,4 @@ export type Reconciler = { ) -> HostContext } -return nil \ No newline at end of file +return nil From f401bab84a89134cedb13451c3f22464d60ef373 Mon Sep 17 00:00:00 2001 From: Amber's Careware <93293456+ambers-careware@users.noreply.github.com> Date: Wed, 17 Nov 2021 12:48:49 -0700 Subject: [PATCH 04/13] Update init.lua --- Pract/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/Pract/init.lua b/Pract/init.lua index d4c36ba..9b55235 100644 --- a/Pract/init.lua +++ b/Pract/init.lua @@ -14,6 +14,7 @@ PractGlobalSystems.Run() -- Public types export type Tree = Types.PractTree export type Component = Types.Component +export type ComponentTyped = Types.ComponentTyped export type Element = Types.Element export type PropsArgument = Types.PropsArgument export type ChildrenArgument = Types.ChildrenArgument From 41727bfe34af3fdcce736208832ad9efe391ecc0 Mon Sep 17 00:00:00 2001 From: Amber's Careware <93293456+ambers-careware@users.noreply.github.com> Date: Wed, 17 Nov 2021 12:50:58 -0700 Subject: [PATCH 05/13] Rename createTyped to createTyped.lua --- Pract/{createTyped => createTyped.lua} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Pract/{createTyped => createTyped.lua} (100%) diff --git a/Pract/createTyped b/Pract/createTyped.lua similarity index 100% rename from Pract/createTyped rename to Pract/createTyped.lua From 6c75c8059f91d946ef27d0b1bcb0450f7942f9bb Mon Sep 17 00:00:00 2001 From: Amber's Careware Date: Wed, 17 Nov 2021 12:54:40 -0700 Subject: [PATCH 06/13] Explicit public typings/silent private typings --- Pract/createTyped.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Pract/createTyped.lua b/Pract/createTyped.lua index c8d498c..b5ba300 100644 --- a/Pract/createTyped.lua +++ b/Pract/createTyped.lua @@ -2,8 +2,12 @@ local Types = require(script.Parent.Types) -local createTyped: (component: (PropsType) -> Types.Element, props: PropsType) = function(component, props) +type CreateTyped = ( + component: (PropsType) -> Types.Element, + props: PropsType +) -> (Types.Element) +local createTyped: CreateTyped = function(component, props) return component(props) -end +end :: any return createTyped From d4594ed35e62fab7157b0957a879246279b4fc18 Mon Sep 17 00:00:00 2001 From: Amber's Careware Date: Wed, 17 Nov 2021 14:35:09 -0700 Subject: [PATCH 07/13] Add forceUpdate to class component self type --- Pract/Types.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Pract/Types.lua b/Pract/Types.lua index 5b9979b..92c4e97 100644 --- a/Pract/Types.lua +++ b/Pract/Types.lua @@ -29,7 +29,8 @@ export type ClassComponentSelf = { self: ClassComponentSelf, partialStateUpdate: ClassStateUpdate ) -> (), - subscribeState: (self: ClassComponentSelf, listener: () -> ()) -> (() -> ()) + subscribeState: (self: ClassComponentSelf, listener: () -> ()) -> (() -> ()), + forceUpdate: (self: ClassComponentSelf) -> (), } export type ClassComponentMethods = { [any]: any, From b34506551effc49dcccc997f3ee43b0ae0e6ffa7 Mon Sep 17 00:00:00 2001 From: Amber's Careware Date: Wed, 17 Nov 2021 15:25:00 -0700 Subject: [PATCH 08/13] Simplify createTyped --- Pract/createTyped.lua | 13 ------------- Pract/init.lua | 5 ++++- 2 files changed, 4 insertions(+), 14 deletions(-) delete mode 100644 Pract/createTyped.lua diff --git a/Pract/createTyped.lua b/Pract/createTyped.lua deleted file mode 100644 index b5ba300..0000000 --- a/Pract/createTyped.lua +++ /dev/null @@ -1,13 +0,0 @@ ---!strict - -local Types = require(script.Parent.Types) - -type CreateTyped = ( - component: (PropsType) -> Types.Element, - props: PropsType -) -> (Types.Element) -local createTyped: CreateTyped = function(component, props) - return component(props) -end :: any - -return createTyped diff --git a/Pract/init.lua b/Pract/init.lua index 9b55235..1273dbc 100644 --- a/Pract/init.lua +++ b/Pract/init.lua @@ -26,7 +26,10 @@ export type Lifecycle = Types.Lifecycle -- Base element functions Pract.create = require(script.create) -Pract.createTyped = require(script.createTyped) +Pract.createTyped = (Pract.create :: any) :: ( + component: (PropsType) -> Types.Element, + props: PropsType +) -> (Types.Element) Pract.index = require(script.index) Pract.stamp = require(script.stamp) Pract.decorate = require(script.decorate) From a54809ded1c02d8ab2a9616c136b19cd72aba614 Mon Sep 17 00:00:00 2001 From: Amber's Careware Date: Wed, 17 Nov 2021 15:25:32 -0700 Subject: [PATCH 09/13] Use exported type --- Pract/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pract/init.lua b/Pract/init.lua index 1273dbc..a326003 100644 --- a/Pract/init.lua +++ b/Pract/init.lua @@ -27,7 +27,7 @@ export type Lifecycle = Types.Lifecycle -- Base element functions Pract.create = require(script.create) Pract.createTyped = (Pract.create :: any) :: ( - component: (PropsType) -> Types.Element, + component: ComponentTyped, props: PropsType ) -> (Types.Element) Pract.index = require(script.index) From c73c309f70585717c08cf3bcfcb6856c214c056d Mon Sep 17 00:00:00 2001 From: Amber's Careware Date: Wed, 17 Nov 2021 19:31:50 -0700 Subject: [PATCH 10/13] Fixed undefined init lifecycle method bug --- Pract/classComponent.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Pract/classComponent.lua b/Pract/classComponent.lua index 0ad9281..b7773c0 100644 --- a/Pract/classComponent.lua +++ b/Pract/classComponent.lua @@ -91,7 +91,9 @@ local function classComponent(componentMethods: Types.ClassComponentMethods) end, init = function(props: Types.PropsArgument) self.props = props - _init(self) + if _init then + _init(self) + end self.state = getState() end, didMount = wrapOptionalLifecycleMethod 'didMount', From bcf76ec1a27837ce812bd57278cfe7fb5a1a2f6a Mon Sep 17 00:00:00 2001 From: Amber's Careware Date: Wed, 17 Nov 2021 20:41:23 -0700 Subject: [PATCH 11/13] Fix class component shouldUpdate bug --- Pract/classComponent.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pract/classComponent.lua b/Pract/classComponent.lua index b7773c0..024482d 100644 --- a/Pract/classComponent.lua +++ b/Pract/classComponent.lua @@ -102,7 +102,7 @@ local function classComponent(componentMethods: Types.ClassComponentMethods) shouldUpdate = function(newProps: Types.PropsArgument) local newState = getState() if _shouldUpdate then - if _shouldUpdate(newProps, newState) == false then + if _shouldUpdate(self, newProps, newState) == false then self.state = getState() self.props = newProps return false From 657bacafea64c975f072469481bba2dd869c1f5d Mon Sep 17 00:00:00 2001 From: Amber's Careware Date: Wed, 17 Nov 2021 21:00:03 -0700 Subject: [PATCH 12/13] Support for none symbol in classComponent setState --- Pract/classComponent.lua | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Pract/classComponent.lua b/Pract/classComponent.lua index 024482d..b8358eb 100644 --- a/Pract/classComponent.lua +++ b/Pract/classComponent.lua @@ -3,6 +3,9 @@ local Types = require(script.Parent.Types) local withDeferredState = require(script.Parent.withDeferredState) local withLifecycle = require(script.Parent.withLifecycle) +local Symbols = require(script.Parent.Symbols) + +local Symbol_None = Symbols.None local INIT_EMPTY_STATE = {} table.freeze(INIT_EMPTY_STATE) @@ -28,6 +31,9 @@ local function classComponent(componentMethods: Types.ClassComponentMethods) if typeof(partialStateUpdate) == 'table' then local stateChanged = false for key, newValue in pairs(partialStateUpdate) do + if newValue == Symbol_None then + newValue = nil + end if saveState[key] ~= newValue then stateChanged = true break @@ -40,6 +46,9 @@ local function classComponent(componentMethods: Types.ClassComponentMethods) newState[key] = value end for key, value in pairs(partialStateUpdate) do + if value == Symbol_None then + value = nil + end newState[key] = value end table.freeze(newState) From fe814989e375850241da91bf063d8b9ed054d23a Mon Sep 17 00:00:00 2001 From: Amber's Careware Date: Wed, 17 Nov 2021 21:09:53 -0700 Subject: [PATCH 13/13] Immediately set state, even if updates deferred --- Pract/createReconciler.lua | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/Pract/createReconciler.lua b/Pract/createReconciler.lua index 4a912eb..cc908a9 100644 --- a/Pract/createReconciler.lua +++ b/Pract/createReconciler.lua @@ -1191,7 +1191,6 @@ local function createReconciler(): Types.Reconciler mountByElementKind[ElementKinds.StateComponent] = function(virtualNode) local currentState = nil :: any - local deferredNextState = nil :: any local stateListenerSet = {} :: {[() -> ()]: boolean} local lastDeferredChangeHeartbeatCount = -1 local function getState() @@ -1208,11 +1207,10 @@ local function createReconciler(): Types.Reconciler return end - local saveState = currentState + currentState = nextState + local element = virtualNode._currentElement if element.deferred then - deferredNextState = nextState - if not virtualNode._collateDeferredState then virtualNode._collateDeferredState = true task.defer(function() @@ -1227,11 +1225,6 @@ local function createReconciler(): Types.Reconciler -- Resume virtualNode._collateDeferredState = nil - if virtualNode._wasUnmounted then - currentState = deferredNextState - return - end - currentState = deferredNextState local listenersToCall = {} for cb in pairs(stateListenerSet) do @@ -1257,8 +1250,6 @@ local function createReconciler(): Types.Reconciler end) end else - currentState = nextState - local listenersToCall = {} for cb in pairs(stateListenerSet) do table.insert(listenersToCall, cb)