Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Rx5 by default #9

Merged
merged 15 commits into from
Sep 25, 2017
Merged

Use Rx5 by default #9

merged 15 commits into from
Sep 25, 2017

Conversation

jseminck
Copy link
Contributor

@jseminck jseminck commented Sep 3, 2017

Started working on porting the library to use Rx5 by default.

  • Updated the getAdapter() and test setup
  • Changed peerDependency from rx to rxjs
  • Updated README
  • Updated blog example: changed to import local rxConnect instead of the version currently on NPM, and refactored the code to use Rx5 syntax
  • Updated wikistream example: changed to import local rxConnect and removed setting up the adapter

What's left to do:

  • Wikistream example is broken (as discussed). It seems wikipedia changed the API
  • Update the docs + codepen examples. I don't think I can do this because they refer to the version hosted on NPM which is still the latest version that uses Rx4 by default. Once the new version is released, I can change these.
  • I have a small wish to replace Codepen by Codesandbox ( https://codesandbox.io ) - it allows specifying the dependencies and pulls them straight from NPM, so it's easier to see what dependencies a project has.

@jseminck
Copy link
Contributor Author

jseminck commented Sep 3, 2017

BTW I am not sure if the adapter approach is really good. We found out that we were including both Rx4 and Rx5 in our bundle because currently rx-connect has a peerDependency on Rx4, even though we wanted to use Rx5.

It turns out we had Rx4 in our node_modules directory because it was a dependency of one of our devDependencies (chimp) and webpack decided to bundle it anyway...

Anyway, this PR will fix that for us. But it might still impact users that want to use the Rx4 version... IMHO it's better just to advice them to use the older version of rx-connect instead (until some new features are added, if ever).

@bsideup
Copy link
Owner

bsideup commented Sep 4, 2017

Hi @jseminck,

Great job! And thanks for pointing me at CodeSandbox, it looks great indeed :)

I'll move code examples from docs to the repo and point CodeSandbox at them, most probably today, so that we can fix the docs together with this PR, ok?

@bsideup
Copy link
Owner

bsideup commented Sep 4, 2017

@jseminck done :) Now you can update the docs with RxJS5, see https://github.com/bsideup/rx-connect/tree/master/examples/docs for sources (FYI you can run locally with yarn serve)

README.md Outdated
@@ -53,7 +53,7 @@ with this:
import { rxConnect } from "rx-connect";

@rxConnect(
Rx.Observable.timer(0, 1000).timestamp()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's weird. The RxJS4 to RxJS5 migration guide actually covers this one specifically:

https://github.com/ReactiveX/rxjs/blob/master/MIGRATION.md

screen shot 2017-09-05 at 10 56 28

I remember it not working at some point, but perhaps it got re-added? Will try because it makes the example a lot simpler and adds "wow factor" 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems it works but need to map it to a plain object now: https://codesandbox.io/s/vn9qjnqovl

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jseminck Hm... I'm thinking maybe we can relax the check here:

.scan((state, mutation) => {
if (isPlainObject(mutation)) {
return Object.assign({}, state, mutation);
}
if (typeof mutation === "function") {
return mutation(state);
}
// eslint-disable-next-line no-console
console.error(`Mutation must be a plain object or function. Check rxConnect of ${getDisplayName(WrappedComponent)}. Got: `, mutation);
return state;

i.e. check if it's function first, if not - do the assignment. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, will try it 😄

Copy link
Contributor Author

@jseminck jseminck Sep 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't really fix the issue here. .timestamp() returns an object, just not a plain object. From the docs: Observable<Timestamp>


What seems to work is adding this (along with lodash.isobject). But I don't know what other implications it has ...

if (isPlainObject(mutation)) {
    return Object.assign({}, state, mutation);
}

if (isObject(mutation)) {
    return Object.assign({}, state, {...mutation});
}

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good to me :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try it and run my branch on our code, to see if things still work 👍

README.md Outdated

## Using Rx4?

This library supports Rx5 by default, but provides an adapter for Rx4:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

library's actual name is "RxJS" :)

.getJSON(`//jsonplaceholder.typicode.com/posts?${ userId ? "userId=" + userId : ""}`)
return Rx.Observable
.ajax(`//jsonplaceholder.typicode.com/posts?${ userId ? "userId=" + userId : ""}`)
.map(e => e.response)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.pluck("response")?

import { connect } from "react-redux";
import wrapActionCreators from "react-redux/lib/utils/wrapActionCreators";
import { rxConnect, ofActions } from "rx-connect";
import { rxConnect, ofActions } from "../../../../src";
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check Webpack's config and alias section. from "rx-connect" was aliasing to the sources actually

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah cool. Yeah that's much nicer. I was confused because rx-connect is also specified as a dependency in the package.json: https://github.com/bsideup/rx-connect/blob/master/examples/blog/package.json#L19

)
export default class Time extends React.PureComponent {
render() {
return <div>{new Date(this.props.timestamp).toLocaleTimeString()}</div>
return <div>{this.props.value} {new Date(this.props.timestamp).toLocaleTimeString()}</div>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{this.props.value} ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was testing stuff.. :D

npm-debug.log Outdated
@@ -0,0 +1,48 @@
0 info it worked if it ends with ok
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oopsy :D

I had to modify getAdapter() in rx-connect --- it was returning as an esModule probably because of the way it was being bundled
through webpack...
@jseminck
Copy link
Contributor Author

jseminck commented Sep 5, 2017

Tackled comments. Updated some examples. Also made examples on Code Sandbox with the current dependency but by changing the adapter: https://codesandbox.io/s/vn9qjnqovl

Some things...

Timestamp

Seems to work, but need to map to a plain object

@rxConnect(
  Rx.Observable
    .timer(0, 1000)
    .timestamp()
    .map(timestamp => ({ ...timestamp }))
)

JSONP

It seems RxJS5 doesn't have JSONP support out of the box, which is needed for the Wikipedia examples. See ReactiveX/rxjs#2095 & ReactiveX/rxjs#1223

As a workaround:

// RxJS5 doesn't support JSONP out of the box
function fetchFromWikipedia(search) {
  return fetchJsonp(
    `https://en.wikipedia.org/w/api.php?action=opensearch&search=${search}&format=json&callback=JSONPCallback`
  ).then(response => response.json());
}

function searchWikipedia(search) {
  return (
    Rx.Observable
      .from(fetchFromWikipedia(search))
      // Wikipedia has really weird response format o_O
      .map(([, titles, , urls]) =>
        titles.map((title, i) => ({ title, url: urls[i] }))
      )
  );
}

Maybe we can find a better example that doesn't need JSONP and we can use plain ajax?

getAdapter()

After changing the example to use webpack alias, I had to change getAdapter(). I think there's some issue in the build process for the blog example.

export function getAdapter() {
    const adapter = rxConnect.adapter || require("./rx5Adapter");
    return adapter.__esModule ? adapter.default : adapter;
}

I'll go over the examples once more later, probably still missed some stuff... The main differences are:

  • flatMapLatest to switchMap
  • debounce to debounceTime
  • .jsonp to ajax
  • The timestamp thing

@jseminck
Copy link
Contributor Author

@bsideup have you seen my comment @ #9 (comment) ?

Otherwise, what else do we need to do to get this in? Would love to have this 😄

README.md Outdated
@@ -53,7 +53,7 @@ with this:
import { rxConnect } from "rx-connect";

@rxConnect(
Rx.Observable.timer(0, 1000).timestamp()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good to me :)


export function fetchUsers() {
return () => {
return Rx.DOM.getJSON(`//jsonplaceholder.typicode.com/users`);
return Rx.Observable.ajax(`//jsonplaceholder.typicode.com/users`).map(e => e.response);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pluck? :)

@bsideup
Copy link
Owner

bsideup commented Sep 20, 2017

@jseminck yeah, sorry for missing that. I left one comment re plain objects and minor one about pluck. Happy to merge once at least the first one is addressed :)

@bsideup
Copy link
Owner

bsideup commented Sep 21, 2017

@jseminck nice! Please also update the examples (Timers) and we're ready to go 🎉

@jseminck
Copy link
Contributor Author

jseminck commented Sep 21, 2017 via email

@bsideup bsideup merged commit f2bff11 into bsideup:master Sep 25, 2017
@bsideup
Copy link
Owner

bsideup commented Sep 25, 2017

@jseminck merged! Thank a lot for your contribution :) Will release it in a few minutes

@jseminck
Copy link
Contributor Author

jseminck commented Sep 25, 2017 via email

@bsideup
Copy link
Owner

bsideup commented Sep 25, 2017

@jseminck released as 0.7.0 🎉

I'll update CodeSandbox and remove JSONP :)

@bsideup
Copy link
Owner

bsideup commented Sep 25, 2017

@jseminck done :) Thanks again :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants