Skip to content

Instantly share code, notes, and snippets.

@inamiy
Last active March 20, 2023 07:19
Show Gist options
  • Save inamiy/c72dc1d0bab3a1db772e34c0be8e18f4 to your computer and use it in GitHub Desktop.
Save inamiy/c72dc1d0bab3a1db772e34c0be8e18f4 to your computer and use it in GitHub Desktop.
SwiftUI emulating React custom hooks (DynamicProperty composition) https://twitter.com/inamiy/status/1313343537132433409
import SwiftUI
struct ContentView: View {
@UseCounter
var counter: Int = 0
@UseCounterEffect(initialCount: 1, onUpdate: { count in
print("===> update: \(count)")
})
var counterEffect: Void
var body: some View {
return VStack {
Text("\(self.counter)")
.padding()
Button("Incr") {
self._counter.increment()
self._counterEffect.increment()
}
}
}
}
@propertyWrapper
struct UseCounter<T: SignedNumeric>: DynamicProperty /*Required*/ {
@State
private var state: T
init(wrappedValue: T) {
self._state = State(wrappedValue: wrappedValue)
}
var wrappedValue: T {
get { state }
}
func increment() {
state += 1
}
}
@propertyWrapper
struct UseCounterEffect<T: SignedNumeric>: DynamicProperty /*Required*/ {
@State
private var state: T
private let onUpdate: (T) -> ()
init(initialCount: T, onUpdate: @escaping (T) -> ()) {
self._state = State(wrappedValue: initialCount)
self.onUpdate = onUpdate
}
// Hide internal values.
var wrappedValue: Void { () }
func update() {
onUpdate(state)
}
func increment() {
state += 1
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment