Skip to content

add re-rxjs #18

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

Merged
merged 1 commit into from
Jun 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,19 @@ in your browser, and click the button very quickly. (check the console log)
check with intensive auto increment
✓ check 8: updated properly with auto increment (3055 ms)
✕ check 9: no tearing with auto increment (2 ms)
re-rxjs
check with events from outside
✓ check 1: updated properly (8274 ms)
✓ check 2: no tearing during update (1 ms)
✓ check 3: ability to interrupt render
✓ check 4: proper update after interrupt (2359 ms)
check with useTransition
✓ check 5: updated properly with transition (4509 ms)
✓ check 6: no tearing with transition (3 ms)
✓ check 7: proper branching with transition (2628 ms)
check with intensive auto increment
✓ check 8: updated properly with auto increment (6106 ms)
✓ check 9: no tearing with auto increment
```

</details>
Expand Down Expand Up @@ -554,6 +567,19 @@ in your browser, and click the button very quickly. (check the console log)
<td>:white_check_mark:</td>
<td>:x:</td>
</tr>

<tr>
<th><a href="https://github.com/re-rxjs/re-rxjs">re-rxjs</a></th>
<td>:white_check_mark:</td>
<td>:white_check_mark:</td>
<td>:white_check_mark:</td>
<td>:white_check_mark:</td>
<td>:white_check_mark:</td>
<td>:white_check_mark:</td>
<td>:white_check_mark:</td>
<td>:white_check_mark:</td>
<td>:white_check_mark:</td>
</tr>
</table>

## Caution
Expand Down
1 change: 1 addition & 0 deletions __tests__/all_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const port = process.env.PORT || '8080';

const names = [
're-rxjs',
'react-redux',
'redux-use-mutable-source',
'reactive-react-redux',
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"build:react-apollo": "cross-env NAME=react-apollo webpack",
"build:recoil": "cross-env NAME=recoil webpack",
"build:effector": "cross-env NAME=effector webpack",
"build:re-rxjs": "cross-env NAME=re-rxjs webpack",
"build-all": "run-s build:*"
},
"keywords": [
Expand All @@ -55,6 +56,7 @@
"graphql": "^15.0.0",
"mobx": "^5.15.4",
"mobx-react-lite": "^2.0.6",
"re-rxjs": "^0.1.0",
"react": "experimental",
"react-dom": "experimental",
"react-hooks-global-state": "^1.0.0",
Expand All @@ -64,6 +66,7 @@
"reactive-react-redux": "^4.9.0",
"recoil": "^0.0.7",
"redux": "^4.0.5",
"rxjs": "^6.5.5",
"storeon": "^2.0.2",
"use-context-selector": "^1.1.1",
"use-subscription": "^1.4.1",
Expand Down
79 changes: 79 additions & 0 deletions src/re-rxjs/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React, { unstable_useTransition as useTransition } from 'react';
import { Subject, merge, asapScheduler } from 'rxjs';
import {
map, scan, startWith, observeOn,
} from 'rxjs/operators';
import { connectObservable } from 're-rxjs';
import {
syncBlock,
useRegisterIncrementDispatcher,
ids,
useCheckTearing,
} from '../common';

const normalClicks$ = new Subject();
const normalIncrement = () => normalClicks$.next();

const externalClicks$ = new Subject();
// This is only needed to prevent the tearing with auto increment (check #9)
Copy link
Owner

Choose a reason for hiding this comment

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

check 9 is to distinguish useSubscription and useMutableSource, so you wouldn't need to treat it specially. I don't know how asapScheduler helps here, but the purpose of the check is not to bypass like that. (I mean, that means the check 9 is not working as I expect.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Both useSubscription and useMutableSource are custom hooks built on top of the existing primitive hooks, meaning that they don't do anything that can't be done from user-land.

I've learned a lot from understanding what they do, and in early versions I was using useSubscription. However, once I better understood what the hook was doing and how RxJS subscriptions behave, I decided to build my own integration for RxJS subscriptions.

The asapScheduler doesn't try to "bypass" a test. That's not at all what it is for. I will document this, but the thing is that when working with the RxJS bindings, if you are subscribed to a data-source that comes from outside of React, then you should be observing it with the asapScheduler because otherwise react won't be able to batch the updates.

So, no, I'm not trying to cheat here 🙂 this is how the bindings should be used with RxJS for inputs that don't come from withing React event-handlers.

const externalClicksAsap$ = externalClicks$.pipe(observeOn(asapScheduler));
const externalIncrement = () => externalClicks$.next();

const [useCounter] = connectObservable(
merge(normalClicks$, externalClicksAsap$).pipe(
scan((x) => x + 0.5, 0),
Copy link
Owner

Choose a reason for hiding this comment

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

Uh, nice.

map(Math.floor),
startWith(0),
),
);

const Counter = React.memo(() => {
const count = useCounter();
syncBlock();
return <div className="count">{count}</div>;
});

const Main = () => {
const count = useCounter();
useCheckTearing();
useRegisterIncrementDispatcher(externalIncrement);
const [localCount, localIncrement] = React.useReducer((c) => c + 1, 0);
const [startTransition, isPending] = useTransition();
const transitionIncrement = () => {
startTransition(() => {
normalIncrement();
});
};

return (
<div>
<button
type="button"
id="normalIncrement"
onClick={isPending ? transitionIncrement : normalIncrement}
Copy link
Owner

Choose a reason for hiding this comment

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

This is weird. Just do this:

Suggested change
onClick={isPending ? transitionIncrement : normalIncrement}
onClick={normalIncrement}

>
Increment shared count normally (two clicks to increment one)
</button>
<button
type="button"
id="transitionIncrement"
onClick={transitionIncrement}
>
Increment shared count in transition (two clicks to increment one)
</button>
<span id="pending">{isPending && 'Pending...'}</span>
<h1>Shared Count</h1>
{ids.map((id) => (
<Counter key={id} />
))}
<div className="count">{count}</div>
<h1>Local Count</h1>
{localCount}
<button type="button" id="localIncrement" onClick={localIncrement}>
Increment local count
</button>
</div>
);
};

export default Main;
7 changes: 6 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6852,6 +6852,11 @@ [email protected]:
iconv-lite "0.4.24"
unpipe "1.0.0"

re-rxjs@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/re-rxjs/-/re-rxjs-0.1.0.tgz#2bb74c717b4a036684047180c67f35af9465ea23"
integrity sha512-0cLFD5rhsbtPw302Usb57oxELzMeZQNDivDLs5ymPrEoFbXSHD/+S0M0e+sm4H+VE6zfz8Ca5y06YlF1zkCOmw==

react-dom@experimental:
version "0.0.0-experimental-33c3af284"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-0.0.0-experimental-33c3af284.tgz#d4acd21209a299832d9233ceafc25a6fe1b1d076"
Expand Down Expand Up @@ -7278,7 +7283,7 @@ rx@^4.1.0:
resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782"
integrity sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=

rxjs@^6.5.3:
rxjs@^6.5.3, rxjs@^6.5.5:
version "6.5.5"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec"
integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==
Expand Down