Mandroid
Mandroid

Reputation: 239

Why the @State value is not updated

I have three buttons, each button corresponds to a value in the data array. When user click a button, the corresponding value will be displayed in a sheet window. Here's my code:

struct TestView: View {
    @State var data: [Int] = [100, 200, 300]
    @State var presented: Bool = false
    @State var index4edit: Int = 1
    
    var body: some View {
        HStack{
            ForEach(1..<4){ index in
                Button(action: {
                    index4edit = index
                    presented.toggle()
                }){ Text(String(index)) }
                .frame(width: 30, height: 30)
                .padding()
            }
        }
        .sheet(isPresented: $presented, content: {
            Text("\(index4edit): \(data[index4edit-1])")
        })
    }
}

My problem is, the first time I click a button, no matter which button, it's always display the first data 100. The reason is that the data index4edit was not updated on the first click, it is always 1, but why? Thanks.

Upvotes: 1

Views: 78

Answers (2)

David Pasztor
David Pasztor

Reputation: 54706

You should set up index4edit to be the real (0-based) index, not index + 1. You should also use data.indices in the ForEach instead of manually inputting the range.

struct TestView: View {
    @State private var data: [Int] = [100, 200, 300]
    @State private var presented: Bool = false
    @State private var index4edit: Int = 0
    
    var body: some View {
        HStack {
            ForEach(data.indices) { index in
                Button(action: {
                    index4edit = index
                    presented.toggle()
                }){ Text(String(index)) }
                .frame(width: 30, height: 30)
                .padding()
            }
        }
        .sheet(isPresented: $presented, content: {
            Text("\(index4edit): \(data[index4edit])")
        })
    }
}

struct TestView_Previews: PreviewProvider {
    static var previews: some View {
        TestView()
    }
}

Upvotes: 0

davidev
davidev

Reputation: 8517

That's because sheet view is created on View initalization. When you change your State, your view won't be recreated because your State variable is not used in your view.

To solve it, just use your State variable somewhere in the code like this dummy example

HStack{
    ForEach(1..<4){ index in
        Button(action: {
            index4edit = index
            presented.toggle()
        }){ Text(String(index) + (index4edit == 0 ? "" : "")) } //<<here is the State used
        .frame(width: 30, height: 30)
        .padding()
    }
}

Now you view will rerender when the State changes, hence your sheet view will be rerendered.

Upvotes: 2

Related Questions