For the sake of discussion, I’ll point out that Angular has FRP “baked in” via the included rxjs library, see this link: Angular
@bhoot, the SolidJS intro you linked to looks very similar to Angular idioms.
It’s an interesting concept, however I wasn’t really satisfied with this paradigm (as is applied in Angular), mainly because one can introduce very subtle and hard to debug bugs, quite easily.
Here’s a minimal example demonstrating a “reactive” data flow. Hopefully it should be self explanatory.
// example.component.ts
import {Component, OnDestroy} from "@angular/core";
import {FormControl, FormGroup} from "@angular/forms";
import {combineLatest, Observable, of, Subject, Subscription, timer} from "rxjs";
import {User, UserService} from "@src/app/services/user.service";
import {catchError, debounceTime, map, startWith, switchMap, tap} from "rxjs/operators";
@Component({
template: `
<h1>Search example</h1>
<form class="search-form" [formGroup]="searchForm" autocomplete="off">
<div>
<label for="firstName">First name</label>
<input id="firstName" type="text" formControlName="firstName">
</div>
<div>
<label for="lastName">Last name</label>
<input id="lastName" type="text" formControlName="lastName">
</div>
<button type="button" (click)="refresh$.next()">Get fresh data</button>
</form>
<div>
<h2>Search result</h2>
<table [class.loading]="loading">
<thead>
<tr>
<th>First name</th>
<th>Last name</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let user of users$ | async">
<td>
{{user.firstName}}
</td>
<td>
{{user.lastName }}
</td>
</tr>
</tbody>
</table>
</div>
`,
})
export class ExampleComponent implements OnDestroy {
searchForm = new FormGroup({
firstName: new FormControl(),
lastName: new FormControl(),
});
loading = false;
refresh$ = new Subject();
userInput$ = combineLatest([
this.searchForm.valueChanges.pipe(debounceTime(200)),
this.refresh$.pipe(
startWith(null), // initiate data flow
),
]);
private refreshSub: Subscription;
userTotal = 0;
users$: Observable<User[]> = this.userInput$.pipe(
tap(_ => this.loading = true),
switchMap(([params, _refresh]) => {
return this.userService.search(params).pipe(
map(({users, total}) => {
this.userTotal = total;
this.loading = false;
return users;
}),
catchError((err) => {
console.log('Oops, something went wrong!');
return of([] as User[]);
}),
);
}),
)
constructor(
private userService: UserService,
) {
this.refreshSub = timer(0, 60_000).subscribe(() => {
this.refresh$.next();
});
}
ngOnDestroy(): void {
this.refreshSub.unsubscribe();
}
}
All that to say that my prior exposure to “FRP” via Angular doesn’t really help me understand the “React” lib (nor the “Note” library for that matter)
Also worth mentioning “rxjs marbles” which are meant to help the programmer “visualize” the application of reactive functions (those functions are named “operators”), see here: RxMarbles: Interactive diagrams of Rx Observables
Crazy to see that “old” flapjax library language!