{"id":15585226,"url":"https://github.com/eveningkid/from-react-to-swiftui","last_synced_at":"2025-04-24T04:11:22.011Z","repository":{"id":147341106,"uuid":"198640960","full_name":"eveningkid/from-react-to-swiftui","owner":"eveningkid","description":"Learn SwiftUI from a React point of view","archived":false,"fork":false,"pushed_at":"2019-07-25T02:59:49.000Z","size":8,"stargazers_count":12,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-24T04:11:19.456Z","etag":null,"topics":["javascript","react","swift","swiftui","web"],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eveningkid.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-07-24T13:27:52.000Z","updated_at":"2023-01-14T18:04:17.000Z","dependencies_parsed_at":"2023-07-15T02:47:28.798Z","dependency_job_id":null,"html_url":"https://github.com/eveningkid/from-react-to-swiftui","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eveningkid%2Ffrom-react-to-swiftui","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eveningkid%2Ffrom-react-to-swiftui/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eveningkid%2Ffrom-react-to-swiftui/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eveningkid%2Ffrom-react-to-swiftui/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eveningkid","download_url":"https://codeload.github.com/eveningkid/from-react-to-swiftui/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250560054,"owners_count":21450173,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","react","swift","swiftui","web"],"created_at":"2024-10-02T21:00:52.634Z","updated_at":"2025-04-24T04:11:21.993Z","avatar_url":"https://github.com/eveningkid.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# From React to SwiftUI\nSwiftUI is great, for many reasons. However, you might want to know how it works, coming from a React background.\n\n- [Basic component](#basic-component)\n- [State](#state)\n- [Props](#props)\n- [Lifecycle](#lifecycle)\n- [Fragments](#fragments)\n- [Style](#style)\n- [Optional rendering](#optional-rendering)\n- [Gestures](#gestures)\n- [Children](#children)\n\nWant to know about some other topics? [Let me know with an issue](https://github.com/eveningkid/from-react-to-swiftui/issues/new).\n\n### Basic component\n```swift\nstruct Home: View {\n  var body: some View {\n    Text(\"Hello\")\n  }\n}\n```\n- `function/class` turns into `struct`\n- `React.Component` becomes `View`, a pure UI element\n- `function return/render(...)` becomes `var body: some View { ... }`\n\n### State\n#### Initialization\nUse the `@State` decorator to define a state property for your component:\n```swift\nstruct Home: View {\n  @State var message = \"Hello\"\n  \n  var body: some View {\n    Text(self.message)\n  }\n}\n```\nPretty straigh-forward. Use `self.stateProperty` instead of `this.state`, just as any struct property.\n\n#### Update\n```swift\nstruct Home: View {\n  @State var message = \"Hello\"\n  \n  var body: some View {\n    Text(self.message).tapAction {\n      self.message = \"Goodbye\"\n    }\n  }\n}\n```\nNo `setState`, no `setProperty`, just update the value right away and the component will re-render accordingly.\n\n### Props\nProps should be defined using component properties:\n```swift\nstruct Home: View {\n  var message: String\n  \n  var body: some View {\n    Text(self.message)\n  }\n}\n```\n- set default values:\n```swift\nvar message: String = \"Goodbye\"\n```\n- props here are just as immutable as in React\n- props **can become** mutable by setting:\n  ```swift\n  // Calling component\n  @State var message = \"Hello\"\n  Home(message: $message)\n\n  // Home\n  @Binding var message: String\n  ```\n  - the property here is a state property, because we need to keep a reference on it as it will be mutated\n  - notice the `$` in front of the `message` variable, indicating that this value is a binding (two-way binding)\n  - `@Binding` indicates this relationship between the child and its parent\n\n### Lifecycle\nPretty limited, as we only get hooks for `didMount` and `willUnmount` using `onAppear` and `onDisappear` respectively:\n```swift\nstruct Home: View {\n  var message: String\n  \n  var body: some View {\n    Text(self.message)\n      .onAppear { print(\"did mount\") }\n      .onDisappear { print(\"did unmount\") }\n  }\n}\n```\n\n### Fragments\nSimilar to `React.Fragment`, `Group` comes handy:\n```swift\nstruct Home: View {\n  var body: some View {\n    Group {\n      Text(\"Hello\")\n      Text(\"Goodbye\")\n    }\n  }\n}\n```\n\n### Style\n#### Basics\nUse view modifiers to define styles:\n```swift\nstruct Home: View {\n  var body: some View {\n    Text(\"Hello\")\n      .font(.title)\n      .foregroundColor(.red)\n      .background(.blue)\n  }\n}\n```\n\n#### Layout\nForget about `div`:\n- use `HStack` for horizontal layout\n- use `VStack` for vertical layout\n- use `ZStack` for stacking views on top of each other\n```swift\nstruct Home: View {\n  var body: some View {\n    // Similar to flex-direction: column\n    VStack {\n      // Similar to flex-direction: row\n      HStack {\n        Text(\"Hello\")\n        Text(\"World\")\n      }\n\n      Text(\"Goodbye\")\n    }\n  }\n}\n```\n\n### Optional rendering\nInstead of `value \u0026\u0026 (...)`, use `if value != nil { ... }`:\n```swift\nstruct Home: View {\n  // String? means that message could not be defined\n  var message: String?\n  \n  var body: some View {\n    Group {\n      if self.message != nil {\n        Text(self.message)\n      }\n    }\n  }\n}\n```\n\n### Gestures\n`onClick` becomes `tapAction`:\n```swift\nstruct Home: View {\n  var body: some View {\n    Text(\"Hello\").tapAction {\n      print(\"Tapped\")\n    }\n  }\n}\n```\nMany more gestures are available, yet less intuitive to implement at first.\n\nMajid 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.\n\n### Children\nThis one can sound a little scary at first, but do not worry, it is only because of Swift syntax.\n```swift\n// !) Important part\n// 1) Define the type of Content: could be View, Label...View is the most generic\nstruct Comments\u003cContent\u003e: View where Content: View {\n  // 2) Add a `content: Content` property\n  let content: () -\u003e Content\n\n  // 3) Set `content` to use `@ViewBuilder` (quite verbose isn't it)\n  init(@ViewBuilder content: @escaping () -\u003e Content) {\n    self.content = content\n  }\n  \n  var body: some View {\n    VStack {\n      // 4) Display \n      content()\n    }\n  }\n}\n\nstruct Comment: View {\n  var author: String\n  var message: String\n  \n  var body: some View {\n    VStack {\n      Text(self.author)\n      Text(self.message)\n    }\n  }\n}\n\n// See children in action\nstruct Home: View {\n  var body: some View {\n    Comments() {\n      Comment(author: \"John\", message: \"Hello\")\n      Comment(author: \"Doe\", message: \"Goodbye\")\n    }\n  }\n}\n```\n\n## Where to go from there?\n- Apple came up with [a great tutorial to get started with SwiftUI](https://developer.apple.com/tutorials/swiftui/tutorials)\n- If you prefer to enjoy great presentations right from WWDC this year:\n  - [SwiftUI On All Devices](https://developer.apple.com/videos/play/wwdc2019/240)\n  - [SwiftUI Essentials](https://developer.apple.com/videos/play/wwdc2019/216)\n- Find more on the great [`awesome-swiftui`](https://github.com/chinsyo/awesome-swiftui) list\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feveningkid%2Ffrom-react-to-swiftui","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feveningkid%2Ffrom-react-to-swiftui","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feveningkid%2Ffrom-react-to-swiftui/lists"}