Skip to content

Commit 674cecc

Browse files
authored
Merge pull request #73 from tonycuadra/tcuadra/fix-function-checks
Make table form of mapDispatchToProps work with callable table actionCreators
2 parents 381f87d + 1e8a0c0 commit 674cecc

File tree

5 files changed

+28
-11
lines changed

5 files changed

+28
-11
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# RoactRodux Changelog
22

33
# Unreleased Changes
4+
* Update function type checks to account for callable tables (like those returned by Rodux.makeActionCreator).
5+
46
## 0.5.1 (2022-05-20)
57
* Expose StoreContext in public API (for use by hooks) ([#56](https://github.com/Roblox/roact-rodux/pull/56))
68

foreman.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
rojo = { source = "rojo-rbx/rojo", version = "=7.2.1" }
33
selene = { source = "Kampfkarren/selene", version = "=0.21.1" }
44
stylua = { source = "JohnnyMorganz/StyLua", version = "=0.15.1" }
5-
luau-lsp = { source = "JohnnyMorganz/luau-lsp", version = "=1.8.1" }
5+
luau-lsp = { source = "JohnnyMorganz/luau-lsp", version = "=1.33.1" }

rotriever.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "RoactRodux"
33
authors = ["Roblox"]
44
license = "Apache-2.0"
55
content_root = "src"
6-
version = "0.5.1"
6+
version = "0.5.2"
77
files = ["*", "!*.spec.lua"]
88

99
[dependencies]

src/connect.lua

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ local function noop()
3232
return nil
3333
end
3434

35+
--[[
36+
Returns `true` if the value can be called i.e. you can write `value(...)`.
37+
]]
38+
local function isCallable(value: any): boolean
39+
return type(value) == "function"
40+
or (type(value) == "table" and getmetatable(value) and getmetatable(value).__call ~= nil)
41+
or false
42+
end
43+
3544
--[[
3645
The stateUpdater accepts props when they update and computes the
3746
complete set of props that should be passed to the wrapped component.
@@ -77,7 +86,7 @@ local function connect<StoreState, Props, MappedStatePartialProps, MappedDispatc
7786
>?
7887
)
7988
if mapStateToPropsOrThunk ~= nil then
80-
assert(typeof(mapStateToPropsOrThunk) == "function", "mapStateToProps must be a function or nil!")
89+
assert(isCallable(mapStateToPropsOrThunk), "mapStateToProps must be a function or nil!")
8190
else
8291
mapStateToPropsOrThunk = noop
8392
end
@@ -142,8 +151,8 @@ local function connect<StoreState, Props, MappedStatePartialProps, MappedDispatc
142151
-- value. In this variant, we keep that value as mapStateToProps
143152
-- instead of the original mapStateToProps. This matches react-redux
144153
-- and enables connectors to keep instance-level state.
145-
if typeof(mappedStoreState) == "function" then
146-
mapStateToProps = mappedStoreState
154+
if isCallable(mappedStoreState) then
155+
mapStateToProps = mappedStoreState :: any
147156
mappedStoreState = mapStateToProps(storeState, self.props.innerProps)
148157
end
149158

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

166175
local mappedStoreDispatch: any
167-
if mapDispatchType == "table" then
176+
if isCallable(mapDispatchToProps) then
177+
mappedStoreDispatch = (mapDispatchToProps :: MapDispatchToProps<StoreState, MappedDispatchPartialProps>)(
178+
(dispatch :: any) :: ThunkfulDispatchProp<StoreState>
179+
)
180+
elseif mapDispatchType == "table" then
168181
mappedStoreDispatch = {}
169182

170183
for key, actionCreator in pairs(mapDispatchToProps :: ActionCreatorMap) do
171-
assert(typeof(actionCreator) == "function", "mapDispatchToProps must contain function values")
184+
assert(isCallable(actionCreator), "mapDispatchToProps must contain function values")
172185

173186
mappedStoreDispatch[key] = function(...)
174187
dispatch(actionCreator(...))
175188
end
176189
end
177-
elseif mapDispatchType == "function" then
178-
mappedStoreDispatch = (mapDispatchToProps :: MapDispatchToProps<StoreState, MappedDispatchPartialProps>)(
179-
(dispatch :: any) :: ThunkfulDispatchProp<StoreState>
180-
)
181190
end
182191

183192
local stateUpdater = makeStateUpdater(self.store)

src/connect.spec.lua

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ return function()
5353
})
5454
end)
5555

56+
it("should accept action creators that are callable tables", function()
57+
connect(nil, {
58+
foo = Rodux.makeActionCreator("Foo", function() end),
59+
})
60+
end)
61+
5662
it("should throw if not passed a component", function()
5763
local selector = function(store)
5864
return {}

0 commit comments

Comments
 (0)