Tal Cohen
Tal Cohen

Reputation: 1457

@State variable doesn't change its value or re-render the view

I'm trying to change a @State from its parent but nothing is changed in the view. I have a simple CustomView with an enum that control its content:

struct CustomView: View {
    enum ViewType: String {
        case first, second, third
    }
    
    @State var viewType: ViewType
    
    var body: some View {
        content
    }
    
    @ViewBuilder private var content: some View {
        switch viewType {
        case .first:
            Text("The first view")
        case .second:
            Text("The second view")
        case .third:
            Text("The last view")
        }
    }
}

And a superview with a button that tries to change its viewType value.

struct ContentView: View {
    let customView = CustomView(viewType: .first)
    var body: some View {
        VStack(spacing: 40) {
            customView
            Button("Change") {
                customView.viewType = .second
            }
        }
    }
}

Maybe I shouldn't use @State but I had no success using Binding with enums. Any idea?

Upvotes: 1

Views: 1384

Answers (1)

jnpdx
jnpdx

Reputation: 52645

Your suspicion about using a @Binding was correct -- the parent view should own the @State and pass it down to the child view.


enum ViewType: String {
    case first, second, third
}

struct ContentView: View {
    @State var viewType: ViewType = .first
    
    var body: some View {
        VStack(spacing: 40) {
            CustomView(viewType: $viewType)
            Button("Change") {
                viewType = .second
            }
        }
    }
}

struct CustomView: View {
    
    @Binding var viewType : ViewType
    
    var body: some View {
        content
    }
    
    @ViewBuilder private var content: some View {
        switch viewType {
        case .first:
            Text("The first view")
        case .second:
            Text("The second view")
        case .third:
            Text("The last view")
        }
    }
}

In general, by the way, it's not a good idea to try to store references to Views like you did with let customView = CustomView(viewType: .first). Instead, the View should be declared in the hierarchy and its state should be passed via parameters (including @Bindings).

Upvotes: 3

Related Questions