mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
3bbfbfad5c
* move imports into files using lettable operators, remove rxjs-library * refactor to be more in keeping with redux conventions from the single reducer.js, I split the functionality into actionTypes (actionTypes.js), actions (actions.js), and epics (epics.js). Most of the fetching should be done in an epic, but that requires introducing a new action and so was better in a separate commit. * switch to fetching on the front-end via an epic The fetching previously was triggered using an api call that had side effects, but was triggered from inside of an epic and was not an action. Now calls on the front-end all of the api calls are occuring via an action through fetchCharacterEpic. This does not remove the api.js file as I have not yet been able to get the epic to trigger correctly on the server-side, thus the api.fetchCharacter call is awaited in getInitialProps for initialising the state serverSide. * remove need for the serverSide api by directly handling the dispatch This still seems to be an incomplete solution to the problem as it circumvents the standard redux event flow on the serverside. However, it does obey the spirit of the redux event flow (as it passes an Observable of an action into the epic to then trigger other actions). Additionally, this removes the problem of code duplication. * update README.md and move lib/ to redux/ * Fix linting
85 lines
2.8 KiB
Markdown
85 lines
2.8 KiB
Markdown
# Redux-Observable example
|
|
|
|
## How to use
|
|
|
|
### Using `create-next-app`
|
|
|
|
Download [`create-next-app`](https://github.com/segmentio/create-next-app) to bootstrap the example:
|
|
|
|
```
|
|
npm i -g create-next-app
|
|
create-next-app --example with-redux-observable with-redux-observable-app
|
|
```
|
|
|
|
### Download manually
|
|
|
|
Download the example [or clone the repo](https://github.com/zeit/next.js):
|
|
|
|
```bash
|
|
curl https://codeload.github.com/zeit/next.js/tar.gz/canary | tar -xz --strip=2 next.js-canary/examples/with-redux-observable
|
|
cd with-redux-observable
|
|
```
|
|
|
|
Install it and run:
|
|
|
|
```bash
|
|
npm install
|
|
npm run dev
|
|
```
|
|
|
|
|
|
### The idea behind the example
|
|
|
|
This example is a page that renders information about Star-Wars characters. It
|
|
fetches new character every 3 seconds having the initial character fetched on
|
|
a server.
|
|
|
|
Example also uses `redux-logger` to log every action.
|
|
|
|
![demo page](demo.png)
|
|
|
|
The main problem with integrating Redux, Redux-Observable and Next.js is
|
|
probably making initial requests on a server. That's because, the
|
|
`getInitialProps` hook runs on the server-side before epics have been made available by just dispatching actions.
|
|
|
|
However, we can access and execute epics directly. In order to do so, we need to
|
|
pass them an Observable of an action and they will return an Observable:
|
|
|
|
```js
|
|
static async getInitialProps({ store, isServer }) {
|
|
const resultAction = await rootEpic(
|
|
of(actions.fetchCharacter(isServer)),
|
|
store
|
|
).toPromise(); // we need to convert Observable to Promise
|
|
store.dispatch(resultAction)};
|
|
```
|
|
|
|
Note: we are not using `AjaxObservable` from the `rxjs` library; as of rxjs
|
|
v5.5.6, it will not work on both the server- and client-side. Instead we call
|
|
the default export from
|
|
[universal-rx-request](https://www.npmjs.com/package/universal-rx-request) (as
|
|
`ajax`).
|
|
|
|
We transform the Observable we get from `ajax` into a Promise in order to await
|
|
its resolution. That resolution should be a action (since the epic returns
|
|
Observables of actions). We immediately dispatch that action to the store.
|
|
|
|
This server-side solution allows compatibility with Next. It may not be
|
|
something you wish to emulate. In other situations, calling or awaiting epics
|
|
directly and passing their result to the store would be an anti-pattern. You
|
|
should only trigger epics by dispatching actions. This solution may not
|
|
generalise to resolving more complicated sets of actions.
|
|
|
|
The layout of the redux related functionality is split between:
|
|
|
|
- actions (in `redux/actions.js`)
|
|
- actionTypes (in `redux/actionTypes.js`)
|
|
- epics (in `redux/epics.js`)
|
|
- reducer (in `redux/reducer.js`)
|
|
|
|
and organized in `redux/index.js`.
|
|
|
|
Excepting in those manners discussed above, the configuration is similar the
|
|
configuration found in [with-redux example](https://github.com/zeit/next.js/tree/canary/examples/with-redux)
|
|
and [redux-observable docs](https://redux-observable.js.org/).
|