diff --git a/Pract/Types.lua b/Pract/Types.lua index 33c6dff..92c4e97 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 @@ -28,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, @@ -97,4 +99,4 @@ export type Reconciler = { ) -> HostContext } -return nil \ No newline at end of file +return nil diff --git a/Pract/classComponent.lua b/Pract/classComponent.lua index 0ad9281..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) @@ -91,7 +100,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', @@ -100,7 +111,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 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) diff --git a/Pract/init.lua b/Pract/init.lua index 01de0af..a326003 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 @@ -25,6 +26,10 @@ export type Lifecycle = Types.Lifecycle -- Base element functions Pract.create = require(script.create) +Pract.createTyped = (Pract.create :: any) :: ( + component: ComponentTyped, + props: PropsType +) -> (Types.Element) Pract.index = require(script.index) Pract.stamp = require(script.stamp) Pract.decorate = require(script.decorate)