Displaying multiple users from http data instead of a single user

115 Views Asked by At

I'm trying to modify the following code so that I receive an array of users from http and display all of them. This code only receives and displays a single user.

import Cycle from '@cycle/core';
import {div, button, h1, h4, a, makeDOMDriver} from '@cycle/dom';
import {makeHTTPDriver} from '@cycle/http';

function main(sources) {
  const USERS_URL = 'http://jsonplaceholder.typicode.com/users/';
  const getAllUsers$ = sources.DOM.select('.get-all').events('click')
    .map(() => {
      return {
        url: USERS_URL + 1,
        method: 'GET'
      };
    });

  const user$ = sources.HTTP
    .filter(res$ => res$.request.url.indexOf(USERS_URL) === 0)
    .mergeAll()
    .map(res => res.body)
    .startWith(null);

  const vtree$ = user$.map(user =>
    div('.users', [
      button('.get-all', 'Get all users'),
      user === null ? null : div('.user-details', [
        h1('.user-name', user.name),
        h4('.user-email', user.email),
        a('.user-website', {href: user.website}, user.website)
      ])
    ])
  );

  return {
    DOM: vtree$,
    HTTP: getAllUsers$
  };
}

const drivers = {
  DOM: makeDOMDriver('#app-main'),
  HTTP: makeHTTPDriver(),
};

Cycle.run(main, drivers);
1

There are 1 best solutions below

0
On BEST ANSWER

You should do one request for multiple users, then iterate over them:

Get all users:

// rather than getting just user 1
url: USERS_URL,

Update this stream:

const users$ = sources.HTTP // users (plural)
.filter(res$ => res$.request.url.indexOf(USERS_URL) === 0)
.mergeAll()
.map(res => res.body)
.startWith([]); // start with an empty array

Generate markup for all users:

users.map(user => 
  div('.user-details', [
    h1('.user-name', user.name),
    h4('.user-email', user.email),
    a('.user-website', {href: user.website}, user.website)
  ])
)

Here's the complete, working code:

function main(sources) {
  const USERS_URL = 'http://jsonplaceholder.typicode.com/users/';
  const getAllUsers$ = sources.DOM.select('.get-all').events('click')
    .map(() => {
      return {
        url: USERS_URL,
        method: 'GET'
      };
    });

  const users$ = sources.HTTP
    .filter(res$ => res$.request.url.indexOf(USERS_URL) === 0)
    .mergeAll()
    .map(res => res.body)
    .startWith([])

  const vtree$ = users$.map(users => {
    return div('.users', [
      button('.get-all', 'Get all users'),
      ...users.map(user => 
        div('.user-details', [
          h1('.user-name', user.name),
          h4('.user-email', user.email),
          a('.user-website', {href: user.website}, user.website)
        ])
      )
    ])
  });

  return {
    DOM: vtree$,
    HTTP: getAllUsers$
  };
}