└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # From React to SwiftUI 2 | SwiftUI is great, for many reasons. However, you might want to know how it works, coming from a React background. 3 | 4 | - [Basic component](#basic-component) 5 | - [State](#state) 6 | - [Props](#props) 7 | - [Lifecycle](#lifecycle) 8 | - [Fragments](#fragments) 9 | - [Style](#style) 10 | - [Optional rendering](#optional-rendering) 11 | - [Gestures](#gestures) 12 | - [Children](#children) 13 | 14 | Want to know about some other topics? [Let me know with an issue](https://github.com/eveningkid/from-react-to-swiftui/issues/new). 15 | 16 | ### Basic component 17 | ```swift 18 | struct Home: View { 19 | var body: some View { 20 | Text("Hello") 21 | } 22 | } 23 | ``` 24 | - `function/class` turns into `struct` 25 | - `React.Component` becomes `View`, a pure UI element 26 | - `function return/render(...)` becomes `var body: some View { ... }` 27 | 28 | ### State 29 | #### Initialization 30 | Use the `@State` decorator to define a state property for your component: 31 | ```swift 32 | struct Home: View { 33 | @State var message = "Hello" 34 | 35 | var body: some View { 36 | Text(self.message) 37 | } 38 | } 39 | ``` 40 | Pretty straigh-forward. Use `self.stateProperty` instead of `this.state`, just as any struct property. 41 | 42 | #### Update 43 | ```swift 44 | struct Home: View { 45 | @State var message = "Hello" 46 | 47 | var body: some View { 48 | Text(self.message).tapAction { 49 | self.message = "Goodbye" 50 | } 51 | } 52 | } 53 | ``` 54 | No `setState`, no `setProperty`, just update the value right away and the component will re-render accordingly. 55 | 56 | ### Props 57 | Props should be defined using component properties: 58 | ```swift 59 | struct Home: View { 60 | var message: String 61 | 62 | var body: some View { 63 | Text(self.message) 64 | } 65 | } 66 | ``` 67 | - set default values: 68 | ```swift 69 | var message: String = "Goodbye" 70 | ``` 71 | - props here are just as immutable as in React 72 | - props **can become** mutable by setting: 73 | ```swift 74 | // Calling component 75 | @State var message = "Hello" 76 | Home(message: $message) 77 | 78 | // Home 79 | @Binding var message: String 80 | ``` 81 | - the property here is a state property, because we need to keep a reference on it as it will be mutated 82 | - notice the `$` in front of the `message` variable, indicating that this value is a binding (two-way binding) 83 | - `@Binding` indicates this relationship between the child and its parent 84 | 85 | ### Lifecycle 86 | Pretty limited, as we only get hooks for `didMount` and `willUnmount` using `onAppear` and `onDisappear` respectively: 87 | ```swift 88 | struct Home: View { 89 | var message: String 90 | 91 | var body: some View { 92 | Text(self.message) 93 | .onAppear { print("did mount") } 94 | .onDisappear { print("did unmount") } 95 | } 96 | } 97 | ``` 98 | 99 | ### Fragments 100 | Similar to `React.Fragment`, `Group` comes handy: 101 | ```swift 102 | struct Home: View { 103 | var body: some View { 104 | Group { 105 | Text("Hello") 106 | Text("Goodbye") 107 | } 108 | } 109 | } 110 | ``` 111 | 112 | ### Style 113 | #### Basics 114 | Use view modifiers to define styles: 115 | ```swift 116 | struct Home: View { 117 | var body: some View { 118 | Text("Hello") 119 | .font(.title) 120 | .foregroundColor(.red) 121 | .background(.blue) 122 | } 123 | } 124 | ``` 125 | 126 | #### Layout 127 | Forget about `div`: 128 | - use `HStack` for horizontal layout 129 | - use `VStack` for vertical layout 130 | - use `ZStack` for stacking views on top of each other 131 | ```swift 132 | struct Home: View { 133 | var body: some View { 134 | // Similar to flex-direction: column 135 | VStack { 136 | // Similar to flex-direction: row 137 | HStack { 138 | Text("Hello") 139 | Text("World") 140 | } 141 | 142 | Text("Goodbye") 143 | } 144 | } 145 | } 146 | ``` 147 | 148 | ### Optional rendering 149 | Instead of `value && (...)`, use `if value != nil { ... }`: 150 | ```swift 151 | struct Home: View { 152 | // String? means that message could not be defined 153 | var message: String? 154 | 155 | var body: some View { 156 | Group { 157 | if self.message != nil { 158 | Text(self.message) 159 | } 160 | } 161 | } 162 | } 163 | ``` 164 | 165 | ### Gestures 166 | `onClick` becomes `tapAction`: 167 | ```swift 168 | struct Home: View { 169 | var body: some View { 170 | Text("Hello").tapAction { 171 | print("Tapped") 172 | } 173 | } 174 | } 175 | ``` 176 | Many more gestures are available, yet less intuitive to implement at first. 177 | 178 | Majid Jabrayilov wrote a really [great article about gestures in SwiftUI](https://mecid.github.io/2019/07/10/gestures-in-swiftui/), that I encourage you to read if you are curious. 179 | 180 | ### Children 181 | This one can sound a little scary at first, but do not worry, it is only because of Swift syntax. 182 | ```swift 183 | // !) Important part 184 | // 1) Define the type of Content: could be View, Label...View is the most generic 185 | struct Comments: View where Content: View { 186 | // 2) Add a `content: Content` property 187 | let content: () -> Content 188 | 189 | // 3) Set `content` to use `@ViewBuilder` (quite verbose isn't it) 190 | init(@ViewBuilder content: @escaping () -> Content) { 191 | self.content = content 192 | } 193 | 194 | var body: some View { 195 | VStack { 196 | // 4) Display 197 | content() 198 | } 199 | } 200 | } 201 | 202 | struct Comment: View { 203 | var author: String 204 | var message: String 205 | 206 | var body: some View { 207 | VStack { 208 | Text(self.author) 209 | Text(self.message) 210 | } 211 | } 212 | } 213 | 214 | // See children in action 215 | struct Home: View { 216 | var body: some View { 217 | Comments() { 218 | Comment(author: "John", message: "Hello") 219 | Comment(author: "Doe", message: "Goodbye") 220 | } 221 | } 222 | } 223 | ``` 224 | 225 | ## Where to go from there? 226 | - Apple came up with [a great tutorial to get started with SwiftUI](https://developer.apple.com/tutorials/swiftui/tutorials) 227 | - If you prefer to enjoy great presentations right from WWDC this year: 228 | - [SwiftUI On All Devices](https://developer.apple.com/videos/play/wwdc2019/240) 229 | - [SwiftUI Essentials](https://developer.apple.com/videos/play/wwdc2019/216) 230 | - Find more on the great [`awesome-swiftui`](https://github.com/chinsyo/awesome-swiftui) list 231 | --------------------------------------------------------------------------------