diff --git a/docs/api-reference.md b/docs/api-reference.md index 40e4639..5075b78 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -268,7 +268,7 @@ end) ``` ### Rodux.makeThunkMiddleware (unreleased) -``` +```lua Rodux.makeThunkMiddleware(extraArgument) -> thunkMiddleware ``` @@ -287,6 +287,29 @@ store:dispatch(function(store, myCustomArg) end) ``` +### Rodux.freezeMiddleware +```lua +local store = Store.new(reducer, initialState, { freezeMiddleware.deep }) +``` + +A function that returns a table of three different middleware functions that prevent you from modifiying the immutable state passed in from the first argument of the reducer. The three functions are `deep`, `shallow`, or `oneLevel` which freeze their respective levels of the table. + +```lua +local freezeMiddleware = Rodux.freezeMiddleware + +local reducer = function(state, action) + local newState = table.clone(state) + + state.money = 5 + --This code will error since you are attempting to modify the + --state table passed in from the reducer and not modifying the clone + + return newState +end + +local store = Store.new(reducer, initialState, { freezeMiddleware.shallow }) +``` + ## Error Reporters In version 3.0.0+, the Rodux store can be provided with a custom error reporter. This is a good entry point to enable improved logging, debugging, and analytics. diff --git a/src/freezeMiddleware.lua b/src/freezeMiddleware.lua new file mode 100644 index 0000000..df73503 --- /dev/null +++ b/src/freezeMiddleware.lua @@ -0,0 +1,44 @@ + +local function deepFreeze(root) + + table.freeze(root) + + for _, value in root do + if typeof(value) == "table" and not table.isfrozen(value) and getmetatable(value) == nil then + deepFreeze(value) + end + end + +end + +return { + deep = function(nextDispatch, store) + return function(action) + deepFreeze(store:getState()) + + return nextDispatch(action) + end + end, + + oneLevel = function(nextDispatch, store) + return function(action) + + for _, value in store:getState() do + if typeof(value) == "table" and not table.isfrozen(value) and getmetatable(value) == nil then + table.freeze(value) + end + end + + return nextDispatch(action) + end + end, + + shallow = function(nextDispatch, store) + return function(action) + + table.freeze(store:getState()) + + return nextDispatch(action) + end + end +} diff --git a/src/init.lua b/src/init.lua index 7ff7531..e7901ef 100644 --- a/src/init.lua +++ b/src/init.lua @@ -6,6 +6,7 @@ local makeActionCreator = require(script.makeActionCreator) local loggerMiddleware = require(script.loggerMiddleware) local thunkMiddleware = require(script.thunkMiddleware) local makeThunkMiddleware = require(script.makeThunkMiddleware) +local freezeMiddleware = require(script.freezeMiddleware) local actions = require(script.types.actions) local reducers = require(script.types.reducers) @@ -31,4 +32,5 @@ return { loggerMiddleware = loggerMiddleware.middleware, thunkMiddleware = thunkMiddleware, makeThunkMiddleware = makeThunkMiddleware, + freezeMiddleware = freezeMiddleware }