Ciprian
Ciprian

Reputation: 3226

Subscribe to array changes

I'm trying to use RxJS in an existing project that uses jQuery. Every time the button is clicked a new value is pushed to users. How do I see changes to users in of(users).subscribe(...)?

<button class="hello">Hello</button>

<script src="https://unpkg.com/rxjs/bundles/rxjs.umd.min.js"></script>

const { of } = rxjs

let users = [
  { a: "b" }
]

of(users).subscribe(data => {
  console.log(data)
})

jQuery(document).on('click', '.hello', function () {
  users.push({ c: 'd' })
})

Upvotes: 2

Views: 2720

Answers (3)

Goga Koreli
Goga Koreli

Reputation: 2947

One way would be to use BehaviorSubject

So for your case would be to write following:

const users$ = new BehaviorSubject([{ a: 'b' }]);

users$.subscribe((users) => {
  console.log(users);
});

jQuery(document).on('click', '.hello', function() {
  const users = [...users$.value]; // write like this so that array stays immutable
  users.push({ a: 'd' });
  users$.next(users);
});

Using BehaviorSubject gives you possibility to obtain current value: users$.value.

After users$.next(users) event will be emitted and console.log(users) will happen inside subscribe

Upvotes: 1

Fan Cheung
Fan Cheung

Reputation: 11370

Alternative you can make use of the new ES6 proxy class together with Subject https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/set

let usersUpdate=new Subject()
let users = [
  { a: "b" }
]

usersUpdate.subscribe(data => {
  console.log(data)
})

let users=new Proxy([{ a: "b" }],{
set:(obj, prop, newval)=>{
    obj[prop] = newval
    userUpdate.next({obj, prop, newval})
    return true
   }
})

users.push('item')

Upvotes: 1

Bennett Hardwick
Bennett Hardwick

Reputation: 1399

Using the RxJS scan operator, you can transform a stream into a different form, similar to how JavaScript's native .reduce() method works. In this example, whenever you wanted to "push" to the users array, you could simply emit another user on the newUser subject.

// Create a new subject
const newUser = new Subject();

// Use scan to add new users into array of users
const users = newUser.pipe(scan((acc, user) => [ ...acc, user ], []));

// Subscribe to the list of users and log
users.subscribe(data => console.log(data));

// Add new user to array on document click
jQuery(document).on('click', '.hello', () => users.next({ c: 'd' }));

Upvotes: 1

Related Questions