Comments (4)
Excellent question. It's really important that this runs on Main Queue. State mutation is exactly the thing you want to run in the main thread, this ensures consistency of multiple incoming actions, and consistency of UI. Your UI is a function of that state, they MUST be in the same thread. Although you could, theoretically, run the reducers in another serial queue and only publish to State Publisher on main queue when reducer is done, there's no real benefit in doing that. Reducer is a pure and sync func, that doesn't perform side-effects or expensive work.
Another point to consider is animations, when UI dispatches an action that will be animatable, you can dispatch it inside a withAnimation block, such as:
withAnimation {
viewModel.dispatch(.tapButtonThatWillFadeSomethingOut)
}
With that code, the State will be reduced in the very same Main Queue Run Loop, StatePublisher will dispatch correctly to perform the animation and you will have the expected behaviour of fading out other elements that are eventually hidden by flags in your AppState. Same for drag gestures.
The optimisation recommended, tho, is to make use of inout State of reducers, and "vars" in your AppState, to avoid copy of arrays (copy-on-modify behaviour) when dealing with larger arrays (maybe more than 100 items, or 50 if the items are really expensive). Another thing that I recommend is keeping Images off the AppState, by using NSCache and keeping on AppState only keys to NSCache and a hash with the current version, I'll try to cover this technique in a further article).
ReduxPipelineWrapper is expected to be initiated from the Main Queue as well (together with the Store), so we collect the Queue ID here:
https://github.com/SwiftRex/SwiftRex/blob/develop/Sources/SwiftRex/CoreTypes/StoreImplementations/ReduxPipelineWrapper.swift#L25
To be used in the "asap" extension here:
https://github.com/SwiftRex/SwiftRex/blob/develop/Sources/SwiftRex/CoreTypes/StoreImplementations/ReduxPipelineWrapper.swift#L68
This ensures that actions coming from the UI will be immediately reduced in the same RunLoop in case we are already in the main queue, which is very likely from UI events (https://github.com/SwiftRex/SwiftRex/blob/develop/Sources/SwiftRex/Foundation/DispatchQueue.swift#L19). Actions coming from Middleware will always be dispatched async to main queue, so they go to the end of the queue and follow the FIFO order. This also avoids that between a "before reducer" and "after reducer" of certain middleware, there are 2 actions changing the state.
Please feel free to play with these things and suggest possible improvements, but please keep in mind all these important protections that avoid race conditions or inconsistencies.
from swiftrex.
It's reasonable, thanks
I was trying to use inout state reducer as you suggested, but it is not included in the latest release (0.7.8)
Will it be released soon?
from swiftrex.
I'm gonna try to finish the tests during these holidays, perhaps postpone documentation to 0.9 or 1.0. But code-wise current develop is expected to be next release, unless the tests uncover some weird bug.
from swiftrex.
Version released.
I'm closing the issue now as it seems to be reasonably answered. Please reopen in case there are still more questions.
from swiftrex.
Related Issues (20)
- middleware lift with WritableKeyPath doesn't work on AnyMiddleware HOT 2
- Fix animations from Middleware
- Dead-Letter Queue HOT 1
- Memory leak in LiftMiddleware
- When will develop be the official release? HOT 2
- Lift EffectMiddleware using KeyPath not receiving context
- How to modify AppLifecycleMiddleware to adopt the new MiddlewareProtocol? HOT 2
- Redundant conformance of 'ASAPScheduler' to protocol 'Scheduler'
- Using await/async in middleware HOT 4
- IO monad and stack limit HOT 6
- I think it's time to enable Enabling Concurrency warnings in Xcode HOT 2
- Dynamic store HOT 5
- Migrate away from Travis CI HOT 4
- Design question : Model to State migration HOT 2
- CombineRex : Unexpected PublisherType behavior HOT 3
- Trying to use Effect.promise with Firebase's DynamicLinkComponents.shortenURL HOT 5
- Question about assertionFailure() HOT 5
- How organize communication between different states HOT 2
- Improve Tests
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from swiftrex.