Skip to content
This repository was archived by the owner on Oct 31, 2024. It is now read-only.

Commit a6abe69

Browse files
committed
4.2.0
- adds `LOCAL_STORAGE_KEY` to `.env`, to allow saving/retrieving MobX store state to `localStorage` on the client - adds `schema/schema.graphql`, with sample schema for Hacker News stories - refactors `<StateConsumer>` as new `withStore()` HOC in `@/lib/store.ts` - refactors `<HackerNews>` example to use the new auto-generayed `<GetHackerNewsTopStories.Component>` - removes default exports in example components - fixes #150 - React-Hot-Loader 4.7 - renames `@/data/state.ts` -> `@/data/store.ts` (now exports `Store` class) - adds `autosave` and new `rehydrate` funcs in `@/lib/store.ts`, for saving and retrieving MobX state to/from `localStorage` - refactors `@/entry/client.tsx` with new MobX store hydration/auto-save - refactors `@/entry/server.tsx` with new MobX store - adds auto-generated `@/graphql/index.tsx` with query and HOC for getting top HackerNews stories - removes previous `@/lib/mobx.ts` - fixes static runner; removes `koa2-history-api-fallback` package in favour of a local function - adds `HOST` to `.env` and `common.host` in runner to allow binding to non-`localhost` - adds `react-dom` alias to Webpack common config, to use `@hot-loader/react-dom`
1 parent 31a95bf commit a6abe69

25 files changed

+2132
-1475
lines changed

.env

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1+
HOST=0.0.0.0
12
GRAPHQL=https://graphqlhub.com/graphql
2-
WS_SUBSCRIPTIONS=0
3+
WS_SUBSCRIPTIONS=0
4+
LOCAL_STORAGE_KEY=reactql

.nvmrc

Lines changed: 0 additions & 1 deletion
This file was deleted.

codegen.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
overwrite: true
2+
schema: "schema/schema.graphql"
3+
documents: "src/**/*.graphql"
4+
generates:
5+
src/graphql/index.tsx:
6+
plugins:
7+
- "typescript-common"
8+
- "typescript-client"
9+
- "typescript-react-apollo"

package-lock.json

Lines changed: 1751 additions & 1211 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "reactql",
3-
"version": "4.1.0",
3+
"version": "4.2.0",
44
"description": "ReactQL - front-end React/GraphQL starter kit",
55
"main": "index.js",
66
"scripts": {
@@ -9,6 +9,7 @@
99
"clean": "rimraf dist",
1010
"dev": "cross-env RUNNER=development NODE_ENV=development ts-node index.ts",
1111
"dev:static": "cross-env RUNNER=static NODE_ENV=development ts-node index.ts",
12+
"gen:graphql": "gql-gen --config codegen.yml",
1213
"production": "cross-env RUNNER=production NODE_ENV=production ts-node index.ts",
1314
"production:clean": "npm run clean && npm run production",
1415
"start": "npm run dev",
@@ -17,8 +18,9 @@
1718
"author": "Lee Benson <lee@leebenson.com>",
1819
"license": "MIT",
1920
"devDependencies": {
20-
"@babel/core": "^7.2.2",
21+
"@babel/core": "^7.3.3",
2122
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
23+
"@hot-loader/react-dom": "^16.8.2",
2224
"@types/compression-webpack-plugin": "^2.0.0",
2325
"@types/history": "^4.7.2",
2426
"@types/html-webpack-plugin": "^3.2.0",
@@ -27,30 +29,34 @@
2729
"@types/koa-router": "^7.0.39",
2830
"@types/koa-send": "^4.1.1",
2931
"@types/koa-webpack": "^5.0.1",
30-
"@types/lodash": "^4.14.120",
32+
"@types/lodash": "^4.14.121",
3133
"@types/mini-css-extract-plugin": "^0.2.0",
32-
"@types/node": "^10.12.18",
34+
"@types/node": "^11.9.4",
3335
"@types/ora": "^3.0.0",
34-
"@types/prop-types": "^15.5.8",
35-
"@types/react": "^16.7.21",
36-
"@types/react-dom": "^16.0.11",
36+
"@types/prop-types": "^15.5.9",
37+
"@types/react": "^16.8.3",
38+
"@types/react-dom": "^16.8.2",
3739
"@types/react-helmet": "^5.0.8",
3840
"@types/react-hot-loader": "^4.1.0",
3941
"@types/react-router-dom": "^4.3.1",
4042
"@types/require-from-string": "^1.2.0",
41-
"@types/source-map-support": "^0.4.1",
43+
"@types/source-map-support": "^0.4.2",
4244
"@types/webpack": "^4.4.24",
43-
"@types/webpack-dev-server": "^3.1.1",
45+
"@types/webpack-dev-server": "^3.1.2",
4446
"@types/webpack-node-externals": "^1.6.3",
4547
"babel-core": "^6.26.3",
4648
"babel-loader": "^8.0.5",
47-
"babel-plugin-emotion": "^10.0.6",
49+
"babel-plugin-emotion": "^10.0.7",
4850
"brotli-webpack-plugin": "^1.1.0",
4951
"compression-webpack-plugin": "^2.0.0",
5052
"css-hot-loader": "^1.4.3",
5153
"css-loader": "^2.1.0",
52-
"cssnano": "^4.1.8",
54+
"cssnano": "^4.1.10",
5355
"file-loader": "^3.0.1",
56+
"graphql-code-generator": "^0.16.1",
57+
"graphql-codegen-typescript-client": "^0.16.1",
58+
"graphql-codegen-typescript-common": "^0.16.1",
59+
"graphql-codegen-typescript-react-apollo": "^0.16.1",
5460
"html-webpack-plugin": "^3.2.0",
5561
"koa-webpack": "^5.2.1",
5662
"less": "^3.9.0",
@@ -60,53 +66,52 @@
6066
"postcss-loader": "^3.0.0",
6167
"postcss-preset-env": "^6.5.0",
6268
"require-from-string": "^2.0.2",
63-
"resolve-url-loader": "^3.0.0",
69+
"resolve-url-loader": "^3.0.1",
6470
"rimraf": "^2.6.3",
6571
"sass-loader": "^7.1.0",
6672
"source-map-support": "^0.5.10",
6773
"ts-loader": "^5.3.3",
6874
"ts-node": "^8.0.2",
6975
"tslint": "^5.12.1",
70-
"typescript": "^3.2.4",
71-
"webpack": "^4.29.0",
76+
"typescript": "^3.3.3",
77+
"webpack": "^4.29.5",
7278
"webpack-node-externals": "^1.7.2"
7379
},
7480
"dependencies": {
75-
"@emotion/core": "^10.0.6",
76-
"@emotion/styled": "^10.0.6",
77-
"apollo-cache-inmemory": "^1.4.2",
78-
"apollo-client": "^2.4.12",
79-
"apollo-link": "^1.2.6",
80-
"apollo-link-error": "^1.1.5",
81-
"apollo-link-http": "^1.5.9",
81+
"@emotion/core": "^10.0.7",
82+
"@emotion/styled": "^10.0.7",
83+
"apollo-cache-inmemory": "^1.4.3",
84+
"apollo-client": "^2.4.13",
85+
"apollo-link": "^1.2.8",
86+
"apollo-link-error": "^1.1.7",
87+
"apollo-link-http": "^1.5.11",
8288
"apollo-link-state": "^0.4.2",
83-
"apollo-link-ws": "^1.0.12",
84-
"apollo-utilities": "^1.1.2",
89+
"apollo-link-ws": "^1.0.14",
90+
"apollo-utilities": "^1.1.3",
8591
"chalk": "^2.4.2",
8692
"cross-env": "^5.2.0",
87-
"cross-fetch": "^3.0.0",
93+
"cross-fetch": "^3.0.1",
8894
"dotenv": "^6.2.0",
89-
"emotion": "^10.0.6",
95+
"emotion": "^10.0.7",
9096
"graphql": "^14.1.1",
9197
"graphql-tag": "^2.10.1",
9298
"history": "^4.7.2",
9399
"kcors": "^2.2.2",
94-
"koa": "^2.6.2",
100+
"koa": "^2.7.0",
95101
"koa-router": "^7.4.0",
96102
"koa-send": "^5.0.0",
97-
"koa2-history-api-fallback": "0.0.5",
98103
"lodash": "^4.17.11",
99104
"microseconds": "^0.1.0",
100105
"mobx": "^4.9.2",
101106
"mobx-react": "^5.4.3",
102-
"ora": "^3.0.0",
103-
"react": "^16.7.0",
107+
"ora": "^3.1.0",
108+
"react": "^16.8.2",
104109
"react-addons-css-transition-group": "^15.6.2",
105110
"react-addons-transition-group": "^15.6.2",
106-
"react-apollo": "^2.4.0",
107-
"react-dom": "^16.7.0",
111+
"react-apollo": "^2.4.1",
112+
"react-dom": "^16.8.2",
108113
"react-helmet": "^5.2.0",
109-
"react-hot-loader": "^4.6.3",
114+
"react-hot-loader": "^4.7.0",
110115
"react-router-dom": "^4.3.1",
111116
"subscriptions-transport-ws": "^0.9.15"
112117
}

schema/schema.graphql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
type Story {
2+
id: String
3+
title: String
4+
url: String
5+
}
6+
7+
type HackerNews {
8+
topStories: [Story]
9+
}
10+
11+
type Query {
12+
hn: HackerNews
13+
}
14+
15+
schema {
16+
query: Query
17+
}

src/components/example/count.tsx

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,15 @@ import * as React from "react";
88

99
/* Local */
1010

11-
// `<StateConsumer>` takes a function and passes it our MobX
12-
// state. Any time the state changes, the children will automatically
13-
// re-render -- no HOCs or boilerplate required!
14-
import { StateConsumer } from "@/lib/mobx";
11+
// `withStore` gives us access to MobX store state
12+
import { withStore } from "@/lib/store";
1513

1614
// ----------------------------------------------------------------------------
1715

18-
export default class Count extends React.Component {
19-
public render() {
20-
return (
21-
<StateConsumer>
22-
{state => (
23-
<>
24-
<h3>Current count (from MobX): {state.count}</h3>
25-
<button onClick={state.increment}>Increment</button>
26-
</>
27-
)}
28-
</StateConsumer>
29-
);
30-
}
31-
}
16+
export const Count = withStore(({ store }) => (
17+
<>
18+
<h3>Current count (from MobX): {store.count}</h3>
19+
<button onClick={store.increment}>Increment</button>
20+
<button onClick={() => (store.count = 0)}>Reset</button>
21+
</>
22+
));

src/components/example/hackernews.tsx

Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,16 @@
66
/* NPM */
77
import * as React from "react";
88

9-
// Use the `<Query>` component from the React Apollo lib to declaratively
10-
// fetch the GraphQL data, to display as part of our component
11-
import { Query } from "react-apollo";
12-
139
// Emotion styled component
1410
import styled from "@emotion/styled";
1511

1612
/* Local */
1713

1814
// Query to get top stories from HackerNews
19-
import hackerNewsQuery from "@/queries/getHackerNewsTopStories";
15+
import { GetHackerNewsTopStories } from "@/graphql";
2016

2117
// ----------------------------------------------------------------------------
2218

23-
// Typescript types
24-
25-
// Represents a HackerNews story - id, title and url
26-
interface IHackerNewsStory {
27-
id: string;
28-
title: string;
29-
url: string;
30-
}
31-
32-
// Represents the data returned by the Hacker News GraphQL query
33-
interface IHackerNewsTopStories {
34-
hn: {
35-
topStories: IHackerNewsStory[];
36-
};
37-
}
38-
3919
// Unstyled Emotion parent block, to avoid repeating <style> tags
4020
// on child elements -- see https://github.com/emotion-js/emotion/issues/1061
4121
const List = styled.ul``;
@@ -55,17 +35,17 @@ const Story = styled("li")`
5535
// whatever the server has sent it - or, if it's a client-navigated route that
5636
// doesn't already have data from the server -- it'll display a loading message
5737
// while the data is being retrieved
58-
export default () => (
59-
<Query<IHackerNewsTopStories> query={hackerNewsQuery}>
60-
{result => {
38+
export const HackerNews: React.FunctionComponent = () => (
39+
<GetHackerNewsTopStories.Component>
40+
{({ data, loading, error }) => {
6141
// Any errors? Say so!
62-
if (result.error) {
63-
return <h1>Error retrieving news stories! &mdash; {result.error}</h1>;
42+
if (error) {
43+
return <h1>Error retrieving news stories! &mdash; {error}</h1>;
6444
}
6545

6646
// If the data is still loading, return with a basic
6747
// message to alert the user
68-
if (result.loading) {
48+
if (loading) {
6949
return <h1>Loading Hacker News stories...</h1>;
7050
}
7151

@@ -75,16 +55,16 @@ export default () => (
7555
<>
7656
<h3>Top stories from Hacker News</h3>
7757
<List>
78-
{result.data!.hn.topStories.map(story => (
79-
<Story key={story.id}>
80-
<a href={story.url} target="_blank">
81-
{story.title}
58+
{data!.hn!.topStories!.map(story => (
59+
<Story key={story!.id!}>
60+
<a href={story!.url!} target="_blank">
61+
{story!.title}
8262
</a>
8363
</Story>
8464
))}
8565
</List>
8666
</>
8767
);
8868
}}
89-
</Query>
69+
</GetHackerNewsTopStories.Component>
9070
);

src/components/example/index.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ import * as React from "react";
1010
/* Local */
1111

1212
// Counter, controlled by local Apollo state
13-
import Count from "./count";
13+
import { Count } from "./count";
1414

1515
// Hacker News GraphQL example
16-
import HackerNews from "./hackernews";
16+
import { HackerNews } from "./hackernews";
1717

1818
// ----------------------------------------------------------------------------
1919

@@ -24,7 +24,7 @@ interface IIndexState {
2424
// Say hello from GraphQL, along with a HackerNews feed fetched by GraphQL
2525
class Index extends React.PureComponent<{}, IIndexState> {
2626
public state = {
27-
dynamic: null
27+
dynamic: null,
2828
};
2929

3030
public componentDidMount = async () => {
@@ -33,7 +33,7 @@ class Index extends React.PureComponent<{}, IIndexState> {
3333

3434
// ... and keep ahold of it locally
3535
this.setState({
36-
dynamic: dynamic.default
36+
dynamic: dynamic.default,
3737
});
3838
};
3939

src/components/root.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
/* NPM */
77
import * as React from "react";
88
import Helmet from "react-helmet";
9-
import { hot } from "react-hot-loader";
9+
import { hot } from "react-hot-loader/root";
1010
import { Route, Switch } from "react-router-dom";
1111
import { Global } from "@emotion/core";
1212

@@ -39,4 +39,4 @@ const Root = () => (
3939
</div>
4040
);
4141

42-
export default hot(module)(Root);
42+
export default hot(Root);

0 commit comments

Comments
 (0)