-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.js
184 lines (156 loc) · 5.92 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// eslint-disable-next-line
window.SOURCE = SOURCE;
var SOURCE = window.SOURCE;
import React from "react";
import ReactDOM from "react-dom";
import {createStore, applyMiddleware, compose} from "redux";
import {Provider} from "react-redux";
import createLogger from "redux-logger";
import {leanReducer, connectLean} from "../src/lean";
import Counter from "./Counter";
import MultipleCounters from "./MultipleCounters";
import ConfiguredCounter from "./ConfiguredCounter";
import DynamicCounters from "./DynamicCounters";
import NamedCounters from "./NamedCounters";
import Async from "./Async";
import RandomGif from "./RandomGif";
import RandomGifPair from "./RandomGifPair";
import RandomGifList from "./RandomGifList";
var enhancers = [
applyMiddleware(createLogger()),
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
].filter(Boolean);
const store = createStore(leanReducer, compose(...enhancers));
const GIF_SCOPE = "gifStuff";
function highlight(sel) {
document.querySelectorAll(sel).forEach(function(block) {
window.hljs.highlightBlock(block);
});
}
const Example = ({source, children}) => (
<div className="example">
<div className="demo">
{children}
</div>
<div className="source">
<div>
<a href={"https://github.com/epeli/lean-redux/blob/master/examples/" + source}>{source}</a>
</div>
<pre>
<code className="javascript">
{(SOURCE[source] || "").trim()}
</code>
</pre>
</div>
</div>
);
var Main = ({gifsVisible, showGifs}) => (
<div>
<h2>Simple counter</h2>
<Example source="Counter.js" >
<Counter />
</Example>
<h2>Multiple Counters</h2>
<p>
Instead of defining the scope in the <em>connectLean</em> HOC
you can define it as a prop. Notice how we can reuse the
component from the previous example just by mounting it to a
antoher part of the state using the <em>scope</em> prop.
</p>
<Example source="MultipleCounters.js" name="">
<MultipleCounters />
</Example>
<h2>Dynamic Counters</h2>
<p>
The <em>scope</em> prop can be dynamic and even go deep into
the state using the array syntax. The path creation works like
in <a href="https://lodash.com/docs/4.16.4#set">Lodash</a>.
</p>
<Example source="DynamicCounters.js" >
<DynamicCounters />
</Example>
<h2>Named Counters</h2>
<p>
This is the standard TODO example (but with added counters!)
demonstrating advanced component scoping.
</p>
<Example source="NamedCounters.js" >
<NamedCounters />
</Example>
<h2>Configured Counter</h2>
<p>
Because the state is in Redux we can access it with normal Redux <em>connect()</em> too.
</p>
<Example source="ConfiguredCounter.js" name="">
<ConfiguredCounter />
</Example>
<h2>Async updates</h2>
<p>
Nothing really special. Like you would do in a component. If the
component is unmounted before the async operation finishes it will
still update the Redux state in the scope.
</p>
<Example source="Async.js" >
<Async />
</Example>
<h2>Random Gif</h2>
<p>
At last we'll partly solve the problem presented at <a href="https://github.com/slorber/scalable-frontend-with-elm-or-redux">slorber/scalable-frontend-with-elm-or-redux</a>.
Partly because with this library you don't write the reducers or
actions yourself (unless you really want to you can of course). So
that part of the "Specification" is ignored.
</p>
<p>
The gif examples will fire some actions on mount so they are not
mounted initially make things cleaner.
</p>
<p>
<a href="#" onClick={showGifs}>Click here the mount them</a>.
</p>
<p>
These gif examples do not use any new concepts anymore.
They are just some more real worldish examples combining async
loading with scopes.
</p>
<p>
For fun we'll scope all of them under <em>gifStuff</em> key in the
Redux state. Checkout
the <a href="https://github.com/epeli/lean-redux/blob/master/examples/index.js">examples/index.js</a> on
github to see how the scope is initialized for them.
</p>
{gifsVisible && <div className="gifs">
<Example source="RandomGif.js" >
<RandomGif tag="robots" scope={[GIF_SCOPE, "single"]} />
</Example>
<h2>Random Gif Pair</h2>
<p>
This should look very familiar. See how the scope is passed
along from the parent component.
</p>
<Example source="RandomGifPair.js" >
<RandomGifPair scope={[GIF_SCOPE, "pair"]} />
</Example>
<h2>Random Gif List</h2>
<p>
This is just a simpler version the Named Counters example. The
fact that the nested components are async doesn't show up here
in anyway.
</p>
<Example source="RandomGifList.js" >
<RandomGifList scope={[GIF_SCOPE, "list"]} />
</Example>
</div>}
</div>
);
Main = connectLean({
getInitialState() {
return {gifsVisible: false};
},
showGifs(e) {
e.preventDefault();
setTimeout(() => highlight(".gifs pre code"), 0);
this.setState({gifsVisible: true});
},
})(Main);
ReactDOM.render(<Provider store={store}><Main /></Provider>, document.getElementById("app"));
highlight("pre code");