Skip to content

Commit

Permalink
Merge pull request #73 from tonycuadra/tcuadra/fix-function-checks
Browse files Browse the repository at this point in the history
Make table form of mapDispatchToProps work with callable table actionCreators
  • Loading branch information
jkelaty-rbx authored Oct 8, 2024
2 parents 381f87d + 1e8a0c0 commit 674cecc
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 11 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# RoactRodux Changelog

# Unreleased Changes
* Update function type checks to account for callable tables (like those returned by Rodux.makeActionCreator).

## 0.5.1 (2022-05-20)
* Expose StoreContext in public API (for use by hooks) ([#56](https://github.com/Roblox/roact-rodux/pull/56))

Expand Down
2 changes: 1 addition & 1 deletion foreman.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
rojo = { source = "rojo-rbx/rojo", version = "=7.2.1" }
selene = { source = "Kampfkarren/selene", version = "=0.21.1" }
stylua = { source = "JohnnyMorganz/StyLua", version = "=0.15.1" }
luau-lsp = { source = "JohnnyMorganz/luau-lsp", version = "=1.8.1" }
luau-lsp = { source = "JohnnyMorganz/luau-lsp", version = "=1.33.1" }
2 changes: 1 addition & 1 deletion rotriever.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "RoactRodux"
authors = ["Roblox"]
license = "Apache-2.0"
content_root = "src"
version = "0.5.1"
version = "0.5.2"
files = ["*", "!*.spec.lua"]

[dependencies]
Expand Down
27 changes: 18 additions & 9 deletions src/connect.lua
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ local function noop()
return nil
end

--[[
Returns `true` if the value can be called i.e. you can write `value(...)`.
]]
local function isCallable(value: any): boolean
return type(value) == "function"
or (type(value) == "table" and getmetatable(value) and getmetatable(value).__call ~= nil)
or false
end

--[[
The stateUpdater accepts props when they update and computes the
complete set of props that should be passed to the wrapped component.
Expand Down Expand Up @@ -77,7 +86,7 @@ local function connect<StoreState, Props, MappedStatePartialProps, MappedDispatc
>?
)
if mapStateToPropsOrThunk ~= nil then
assert(typeof(mapStateToPropsOrThunk) == "function", "mapStateToProps must be a function or nil!")
assert(isCallable(mapStateToPropsOrThunk), "mapStateToProps must be a function or nil!")
else
mapStateToPropsOrThunk = noop
end
Expand Down Expand Up @@ -142,8 +151,8 @@ local function connect<StoreState, Props, MappedStatePartialProps, MappedDispatc
-- value. In this variant, we keep that value as mapStateToProps
-- instead of the original mapStateToProps. This matches react-redux
-- and enables connectors to keep instance-level state.
if typeof(mappedStoreState) == "function" then
mapStateToProps = mappedStoreState
if isCallable(mappedStoreState) then
mapStateToProps = mappedStoreState :: any
mappedStoreState = mapStateToProps(storeState, self.props.innerProps)
end

Expand All @@ -164,20 +173,20 @@ local function connect<StoreState, Props, MappedStatePartialProps, MappedDispatc
end

local mappedStoreDispatch: any
if mapDispatchType == "table" then
if isCallable(mapDispatchToProps) then
mappedStoreDispatch = (mapDispatchToProps :: MapDispatchToProps<StoreState, MappedDispatchPartialProps>)(
(dispatch :: any) :: ThunkfulDispatchProp<StoreState>
)
elseif mapDispatchType == "table" then
mappedStoreDispatch = {}

for key, actionCreator in pairs(mapDispatchToProps :: ActionCreatorMap) do
assert(typeof(actionCreator) == "function", "mapDispatchToProps must contain function values")
assert(isCallable(actionCreator), "mapDispatchToProps must contain function values")

mappedStoreDispatch[key] = function(...)
dispatch(actionCreator(...))
end
end
elseif mapDispatchType == "function" then
mappedStoreDispatch = (mapDispatchToProps :: MapDispatchToProps<StoreState, MappedDispatchPartialProps>)(
(dispatch :: any) :: ThunkfulDispatchProp<StoreState>
)
end

local stateUpdater = makeStateUpdater(self.store)
Expand Down
6 changes: 6 additions & 0 deletions src/connect.spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ return function()
})
end)

it("should accept action creators that are callable tables", function()
connect(nil, {
foo = Rodux.makeActionCreator("Foo", function() end),
})
end)

it("should throw if not passed a component", function()
local selector = function(store)
return {}
Expand Down

0 comments on commit 674cecc

Please sign in to comment.