How to do network request without clicking at button

Viewed 56

I have a textfield and I need that when I write smth. in textfield it sends request to server without clicking at any button. For example if my sending text is the same as server's text it print that text. I am using SwiftUI and Combine. Below is my code.

@State var cancellable: AnyCancellable?
     .onReceive(Just($homePageVM.orderNumber)) { res in
            if !homePageVM.orderNumber.isEmpty {
                cancellable = homePageVM.orderNumber
                    .publisher
                    .receive(on: RunLoop.main)
                    .sink(receiveCompletion: { completion in
                        print(completion)
                    }, receiveValue: { value in
                        homePageVM.getVoucherInfo { result in
                            if homePageVM.orderNumber == homePageVM.getVoucherInfoModel?.orderNumber {
                                print(result)
                            }
                        }
                    })
            }
        }

I am using onreceive because I need to send the data every time i change the text. But in the result i receive an unended cycle. How can i send data only one time every time I change my text? Please help me.

1 Answers

It is very strange to use onReceive with Just and sink, there is no point in using Combine at all. The onChange modifier would replace all of this. However, the best way to do what you need simply with multiple View structs and the task modifier, e.g.

struct View1: View {

    ...

    var body: some View {
        View2(orderNumber: model.orderNumber)
    }
}

struct View2: View {
    let orderNumber: Int
    @State var result: String?

    // body called when any of the properties change
    var body: some View {
        Text(result ?? "No result")
        .task(id: orderNumber) { newOrderNumber in
            result = await fetchVoucherInfo(orderNumber: newOrderNumber)
        } // The `task` is started if the orderNumber has changed.
    }
}
Related