FormControl.detectchanges - why use distinctUntilChanged?

distinctUntilChanged when applied to the valueChanges observable...

...is probably never going to work!

It only works as expected on an individual value (as you said). So you'll get a new value even if nothing has changed.

To track changes for the whole form you need to write a custom comparer, the simplest of which uses JSON.stringify to output a value that can be compared. The valueChanges observable emits an object and distinctUntilChanges isn't smart enough to do anything beyond a reference compare (that's a link to the RxJS source code) unless you provide a comparer function.

this.form.valueChanges.pipe(distinctUntilChanged((a, b) => JSON.stringify(a) === 
                                                           JSON.stringify(b)))

                      .subscribe(changes => { console.log('The form changed!'); });

distinctUntilChanged works fine for an individual value with a primitive type because === is sufficient to detect changes.

How do I solve infinite loops?

If you're trying to add distinctUntilChanges into your pipe (for the whole form) to avoid an infinite loop when you programmatically update the form value - you probably want this instead:

    this.form.patchValue(address || {}, { emitEvent: false });

Using debounceTime(1000) means we only send a request when the user stopped typing for 1 second, during that second the user can write 3 characters then erase them, so the input value didn't change since last request but you are sending the same request, to avoid that you can use .distinctUntilChanged()

  this.myFormControl.valueChanges
      .debounceTime(1000)
      .distinctUntilChanged()
      .subscribe(newValue => {
        console.log('debounced: ', newValue)
      });