This is my code:
struct TestPageView: View {
@State var blocks: [String] = ["1", "2", "3"]
var body: some View {
VStack {
ForEach(blocks, id: \.self) { block in
TestView(block, $blocks)
}
}
}
}
struct TestView: View {
@Binding var blocks: [String]
let block: String
init(_ block: String, _ blocks: Binding<[String]>){
print("Created empty view")
self.block = block
self._blocks = blocks
}
var body: some View {
TextField("Test view", text: .constant(block), onCommit: {
print("Committed")
blocks.append("new element")
})
}
}
Basic idea is that my ForEach loops over my blocks, showing them. When a user performs an action while a block is focused (onCommit here), I need a new block to be added to the list. This code actually does that correctly; the problem is with performance. With the above print statements, the following is the output:
Created empty view
Created empty view
Created empty view
Committed
Created empty view
Created empty view
Created empty view
Created empty view
so it seems the ForEach re-renders all of the items in the list. In this simple example, it's not an issue, but in my real problem, recreating all the TestViews is a large task, and completely unnecessary: I just need the new element to be added, everything else can be left the same. Is there a good way to do this?
Note: The \.self is not the issue. I've tried this with making the "blocks" conform to Identifiable. The ForEach still fails to recognize the same ids and still creates the views again.