Passing @State to Subviews

In the previous segment, you learned how to properly initialize @State properties and a pitfall to watch out for when passing @State from parent to child subview. Building on that foundation, this segment explores how to properly pass state to a child subview and introduces the concept of statelessness in SwiftUI views.

Passing Read-Only State to Subviews

When a @State property’s value is passed to a subview, the subview can read that value, and SwiftUI will update the subview whenever the value changes in the parent view. However, the subview cannot directly modify that value. To enable the subview to modify the state’s stored value, a different property wrapper called @Binding must be used instead. @Binding will be covered in detail in the next lesson.

To see how a read-only state can be passed, consider this example where the ContentView’s count state is successfully displayed by its child CounterView:

struct ContentView: View {
    @State private var parentCount: Int = 0

    var body: some View {
        VStack {
            CounterView(count: parentCount)
            Button("Increment") {
                parentCount += 1
            }
        }
    }
}

struct CounterView: View {
    let count: Int

    var body: some View {
        Text("Count: \(count)")
    }
}

If count changes in ContentView, CounterView will automatically update to reflect the new read-only value.

How is this different than the pitfall example from the last segment? In both examples, the parent ContentView has a @State property count and passes its value to the child CounterView. However, this time, CounterView doesn’t declare count as its own @State; rather, it’s an unmodifiable let property. The @State remains managed locally by its owning view: ContentView.

Understanding Statelessness in SwiftUI Views

In the last module, you observed that none of the UI could change after the first display. This was because none of the views in the view hierarchy had state. An app with a view hierarchy consisting entirely of views without state can’t change its UI after the first display. However, as soon as state is introduced in one of the views in the view hierarchy, that view and all its subviews are now able to change their UI after the first display, even the subviews that don’t have any state of their own.

This concept is crucial for understanding how data flows and changes in a SwiftUI app. A view without its own state is considered “stateless”. While a stateless view can’t directly change its own UI based on internal events, it can still update its UI in response to changes in state passed down from a parent view.

In the example, the CounterView is stateless. But, even though CounterView doesn’t have its own @State property, it can still display updated values for count because it receives this state from ContentView.

Case in point: Use @State sparingly. You might be tempted to think, “I need this view’s UI to change after the first display, so this view needs @State.” But this isn’t always the case. If you need the UI to update, you likely don’t need state in every single view. You can write a stateless view and have it update when a parent’s state changes.

When to Use @State

So, how do you know when to use @State? If your particular view listens to (or “observes”) events that modify its display or value of internally managed data, use @State. However, consider which view in the hierarchy should own that @State.

A common event that might trigger such a change is a button press. Think of the counter example: A button press to Increment sends an event that should update the display and internal view state.

Did each view in the hierarchy need @State? No, only one manages and owns that state and passes its value as needed. Any child view of ContentView that needs to display count can remain stateless.

Practicing Sharing State

Understanding how to pass state to subviews and the concept of statelessness in SwiftUI views are key to building dynamic and interactive apps. In the upcoming video demo, you’ll get hands-on practice with these concepts, further solidifying your understanding of state management in SwiftUI.

See forum comments
Download course materials from Github
Previous: Initializing @State Properties Demo Next: Passing @State to Subviews Demo