Auto archive state when state changes
ethanyuwang opened this issue · comments
In the movie example app, I saw it uses a timer to archive the state every other 30 seconds.
https://github.com/Dimillian/MovieSwiftUI/blob/2897f8dfd3ea8370fbecacf56a8516f25d71efe8/MovieSwift/MovieSwift/views/components/home/HomeView.swift#L23
I would like the state to archive right after when a user is authenticated to save authenticated: true
, so next time when user opens the app it doesn't load the sign-in screen. Is there a way to subscribe to state change and auto archive state when state changes?
Hi @ethanyuwang, sure you can subscribe to state updates using a middleware. Here’s a sketch of how you might do it (error handling is an exercise for you 😇):
let stateArchiverMiddleware: Middleware<FluxState> = { dispatch, getState in
return { next in
return { action in
let state = getState() as! MyAppState
let folder = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let file = folder.appendingPathComponent("MyAppState.json")
try! JSONEncoder().encode(state).write(to: file)
return next(action)
}
}
}
The other thing you’ll need to do if you want to get your state restored is write a routine to read it back in on app launch (again, just an outline — make sure to put some error handling in):
func loadMyAppState() -> MyAppState? {
let folder = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let data = try! Data(contentsOf: folder.appendingPathComponent("MyAppState.json")),
return try? JSONDecoder().decode(MyAppState.self, from: data)
}
You’ll need to specify the middleware and load routine when creating your store:
let myStore = Store<MyAppState>(reducer: myAppReducer, middleware: [stateArchiverMiddleware], state: loadMyAppState() ?? MyAppState())
Hey, I might be late to the party but since we built upon your solution @danhalliday (so thanks for your reply here!) I wanted to mention that calling next(action)
at the very end of the function will cause you to save the state before the actual action runs which modifes it. Calling it at the beginning of the closure like let nextAction = next(action)
and then returning nextAction
will resolve that.