Replies: 1 comment
-
+1 for this idea of read-only persistent external state. I haven't had a chance to play with the shared state beta yet, but this is exactly the use case (emulating SwiftData While, it is not entirely true that the Reducers don't modify the underlying state. I certainly do make changes to the underlying persistent data in some of my Reducers. However, I don't try to mutate the So instead, the underlying datastore is modified through its own dependency, and the |
Beta Was this translation helpful? Give feedback.
-
I'm happy to say that so far I have had a smooth transition to
@Shared
in one of my projects. It cleaned up a very complex solution I had before to achieve the same functionality with a custom persistence client and custom reducer operator for synchronizing the data. However, during this process, I and some others have seemingly noted a particular kind of shared state that is read-only. After some brainstorming, I think it would be best if the library could provide better tooling for representing this kind of shared state.In particular, I have noticed 2 kinds of shared state:
@Query
in swift-data, GRDB value observations, the current user's location, etc.I think number 1 tends to be the more common case, but number 2 in my opinion is far more interesting since I believe the current shared state tools would add some unnecessary overhead in implementing it. Therefore, I want to focus most of this on number 2, but what I have in mind should work for both cases.
So utilizing the current tools for number 2, assuming that we have some kind of
PersistenceKey
conformance that behaves like@Query
in swift-data, and that we have some conversion process from@Model
to value types. Then the following would be quite non-sensical:This case would mirror why
@Query
is read-only in swift data. In this case, the reducer, or rather any reducer for that matter, has no business mutating the array of events since it could add an invalid event that wouldn't represent the query in@Shared
.For the point on mutations, since
@Shared
already allows mutations to its value, so we'll need a new property wrapper that prevents mutations to its value. A good name for this would be@External
since it would represent a value that's strictly external to the reducer.@External
would have a similar overload as@Shared
withPersistenceKey
, so that should cover the first case of shared state that I mentioned where a small handful of reducers can mutate the state whilst others can only read the state.However, on the topic of
PersistenceKey
s, the hypothetical@Query
-like persistence key entirely controls the state of the query.PersistenceKey
has some protocol requirements that introduce unnecessary overhead in implementing these kinds of read-only persistence keys, mainly due to the save method and the optionalValue
associated type. A new protocol for read-only persistence keys would be ideal, something like:The main thing here besides the lack of a save method, is unlike
PersistenceKey
load
andupdates
don't deal with an optionalValue
. This is because in theory there should be a sensible default that is entirely controlled by the external system, like an empty array of events if none could be found from the query in the earlier example.Using this protocol, there could then be an overload init of
@External
that allows for the usage ofExternalKey
like:Then, this would change the query example from before to:
Overall, I'm enjoying using
@Shared
, and I see a lot of parallels with the shared state tools, anduseSyncExternalStore
from the react world. As such I modeled theExternalKey
protocol similarly to the function parameters ofuseSyncExternalStore
.Beta Was this translation helpful? Give feedback.
All reactions