Skip to content

Instantly share code, notes, and snippets.

@mattpodwysocki
Created April 15, 2015 21:25
Show Gist options
  • Save mattpodwysocki/0697e8c7d317998170da to your computer and use it in GitHub Desktop.
Save mattpodwysocki/0697e8c7d317998170da to your computer and use it in GitHub Desktop.
Getting a list of users with RxJS and JSX
<!DOCTYPE html>
<html>
<head>
<meta http-equiv='Content-type' content='text/html; charset=utf-8'>
<title>Basic Example with JSX</title>
<link rel="stylesheet" href="base.css" />
</head>
<body>
<h1>ReactJs + RxJs</h1>
<div id="container">
<p>
If you can see this, React is not working right.
If you checked out the source from GitHub make sure to run <code>grunt</code>.
</p>
</div>
<h4>Example Details</h4>
<p>This is written with JSX and transformed in the browser.<p>
<script src="https://code.jquery.com/jquery-2.1.3.js"></script>
<script src="http://fb.me/react-0.13.1.min.js"></script>
<script src="http://fb.me/JSXTransformer-0.13.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/2.5.1/rx.all.js"></script>
<script type="text/jsx">
function getData(url) {
return jQuery.ajax({
url: url,
dataType: 'jsonp'
}).promise();
}
var subject = new Rx.BehaviorSubject('https://api.github.com/users');
var responseStream = subject.flatMap(getData);
var ExampleApplication = React.createClass({
getInitialState: function() {
return { data: [] };
},
componentDidMount: function() {
var self = this;
responseStream.subscribe(function (response) {
self.setState( { data: response.data } );
self.forceUpdate();
});
},
getMoarUsers: function(e){
var randomOffset = 'https://api.github.com/users?since=' + Math.floor(Math.random()*500);
subject.onNext(randomOffset);
},
render: function() {
var message = this.state.data.map(function (user) {
return (
<div>
{user.login}
</div>
);
});
return (<div>
{message}
<div><button onClick={ this.getMoarUsers }>Get moar users</button></div>
</div>);
}
});
React.render(
<ExampleApplication />,
document.getElementById('container')
);
</script>
</body>
</html>
@zxbodya
Copy link

zxbodya commented Apr 17, 2015

A bit off topic, but likely this would be quite helpful for anyone who are starting to work with React and Rx.
It is what I learned while using Rx with React:
https://gist.github.com/zxbodya/20c63681d45a049df3fc

In short - It is better to create stream of elements to render, instead of creating complicated component that will render data directly from streams.

Just to illustrate what I mean - example above can be rewritten as following:

function getData(url) {
  return jQuery.ajax({
    url: url,
    dataType: 'jsonp'
  }).promise();
}

var subject = new Rx.BehaviorSubject('https://api.github.com/users');

var responseStream = subject
  .flatMap(getData)
  .map(function (response) {
    return response.data;
  });

function getMoreUsers() {
  var randomOffset = 'https://api.github.com/users?since=' + Math.floor(Math.random() * 500);
  subject.onNext(randomOffset);
}

var ExampleApplication = React.createClass({
  render: function () {
    var message = this.props.data.map(function (user) {
      return (<div>{user.login}</div>);
    });

    return (
      <div>
        {message}
        <div>
          <button onClick={this.props.getMoreUsers}>Get moar users</button>
        </div>
      </div>
    );
  }
});

var container = document.getElementById('container');
Rx.Observable.return([]).merge(responseStream)
.subscribe(function (data) {
  React.render(<ExampleApplication data={data} getMoreUsers={getMoreUsers}/>, container);
});

Just some of benefits:

  • ExampleApplication can be optimised using pure render mixin
  • ExampleApplication is just a view - nothing complicated inside (easier to test or reuse)
  • it is "more isomorphic" almost the same code can be used on server side
  • no need to pass default value(we can replace Rx.Observable.return([]).merge(responseStream) above by just responseStream, and first render will happen after data will be received)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment