Давайте вспомним, что SwiftUI является реактивным (ie. Управляемым состоянием, а не управляемым событиями), поэтому, если мы не хотим что-то менять в пользовательском интерфейсе, нам нужно найти способ изменить это через состояние (пользовательский интерфейс или модель, но состояние).
Итак, ниже немного изменен ваш код, чтобы показать возможный подход. Протестировано с Xcode 11.2 / iOS 13.2.

struct ContentView: View {
@State var data : [String] = ["first","second","third","4th","5th"]
@State private var selectedItem: String? = nil
var body: some View {
List {
ForEach (data, id: \.self) {
item in
ColoredRow(text: item, selection: self.$selectedItem)
}
}
}
}
struct ColoredRow: View {
var text: String = ""
@Binding var selection: String?
@State var col : Color = Color.white
var body: some View{
Text("\(text)")
.background(selection == text ? Color.red : Color.white)
.onTapGesture {
self.selection = (self.selection == self.text ? nil : self.text)
}
}
}