PageSourceSearch

https://fluxxor.com/guides/quick-start.html

html fluxxor.com collected 2026-10-03 23:49:22 UTC 16,372 bytes, 336 lines download raw bytes

1<!doctype html>
2<html lang="en">
3
4<meta charset="utf-8">
5<title>Fluxxor - Quick-Start Guide</title>
6<meta name="viewport" content="width=device-width, initial-scale=1.0">
7<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
8<meta property="og:image" content="http://fluxxor.com/fluxxor.png">
9<meta property="og:site_name" content="Fluxxor">
10<meta name="twitter:card" content="summary">
11<meta name="twitter:site" content="">
12<meta name="twitter:title" content="Fluxxor">
13<meta name="twitter:description" content="Fluxxor is a set of tools to facilitate building JavaScript data layers using the Flux architecture.">
14<meta name="twitter:creator" content="BinaryMuse">
15<meta name="twitter:image:src" content="http://fluxxor.com/fluxxor.png">
16<meta name="twitter:domain" content="">
17<meta name="twitter:app:name:iphone" content="">
18<meta name="twitter:app:name:ipad" content="">
19<meta name="twitter:app:name:googleplay" content="">
20<meta name="twitter:app:url:iphone" content="">
21<meta name="twitter:app:url:ipad" content="">
22<meta name="twitter:app:url:googleplay" content="">
23<meta name="twitter:app:id:iphone" content="">
24<meta name="twitter:app:id:ipad" content="">
25<meta name="twitter:app:id:googleplay" content="">
26<link rel="stylesheet" href="http://yandex.st/highlightjs/8.0/styles/default.min.css">
27<script src="http://cdnjs.cloudflare.com/ajax/libs/es5-shim/3.4.0/es5-shim.min.js"></script>
vendor: 1 bytes, line 27
27
28<script src="http://yandex.st/highlightjs/8.0/highlight.min.js"></script>
vendor: 1 bytes, line 28
28
29<script>hljs.initHighlightingOnLoad();</script>
29
30<link rel="stylesheet" type="text/css" href="/style/main.css">
31
32<a class="github-banner" href="https://github.com/BinaryMuse/fluxxor"><img style="position: fixed; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/a6677b08c955af8400f44c6298f40e7d19cc5b2d/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f677261795f3664366436642e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png"></a>
33
34<div class="wrapper">
35  <header>
36    <div class="logo-container-sidebar">
37      <a href="/"><img src="/fluxxor.svg" alt="Fluxxor" title="Fluxxor" class="logo-svg"></a>
38    </div>
39    <div class="show-hide-nav">
40      <a href="#" class="show-nav">Show Navigation</a>
41      <a href="#" class="hide-nav">Hide Navigation</a>
42    </div>
43    <div class="nav-list">
44      <ul>
45        <li><a href="/">Home</a></li>
46        <li><a href="/what-is-flux.html">What is Flux?</a></li>
47        <li><a href="/guides/">Guides</a></li>
48        <ul>
49          <li><a href="/guides/installation.html">Installation</a></li>
50          <li><a href="/guides/react.html">Using with React</a></li>
51          <li><a href="/guides/quick-start.html">Quick-Start Guide</a></li>
52          <li><a href="/guides/async-data.html">Dealing with Asynchronous Data</a></li>
53          <li><a href="/guides/routing.html">Routing</a></li>
54        </ul>
55        <li><a href="/examples/">Examples</a></li>
56        <ul>
57          <li><a href="/guides/quick-start.html">Basic Todos</a></li>
58          <li><a href="/examples/carousel/">Image Carousel</a></li>
59          <li><a href="/guides/async-data.html">Asynchronous Data</a></li>
60          <li><a href="/examples/react-router.html">React Router</a></li>
61        </ul>
62        <li><a href="/documentation/">Documentation</a></li>
63        <ul>
64          <li><a href="/documentation/flux.html">Fluxxor.Flux</a></li>
65          <li><a href="/documentation/stores.html">Stores</a></li>
66          <li><a href="/documentation/actions.html">Actions</a></li>
67          <li><a href="/documentation/flux-mixin.html">Fluxxor.FluxMixin</a></li>
68          <li><a href="/documentation/store-watch-mixin.html">Fluxxor.StoreWatchMixin</a></li>
69        </ul>
70        <li><a href="/faq.html">FAQ</a></li>
71        <li><a href="/changelog.html">Changelog</a></li>
72        <li><a href="https://github.com/BinaryMuse/fluxxor">View on GitHub</a></li>
73      </ul>
74      <p>
75        <a href="https://gitter.im/BinaryMuse/fluxxor">Support and chat on Gitter</a><br>
76        <a href="https://gitter.im/BinaryMuse/fluxxor"><img src="https://badges.gitter.im/BinaryMuse/fluxxor.png"></a>
77      </p>
78    </div>
79    <div class="sidebar-info">
80      <hr>
81      <p>Copyright &copy; 2014 <a href="https://github.com/BinaryMuse/">Michelle Tilley</a><br>
82      Licensed under <a href="http://opensource.org/licenses/MIT">the MIT license</a></p>
83    </div>
84  </header>
85  <section>
86    <h1 id="quick-start-guide-basic-todos-example">Quick-Start Guide / Basic Todos Example</h1>
87<p>Once you have Fluxxor and React <a href="/guides/installation.html">installed</a>, it&#39;s time to build an app! Since this guide is designed to cover the basics quickly, we&#39;ll start with a <em>very</em> basic todo app—namely, this one right here:</p>
88<div id="app"></div>
89
90<h2 id="stores-and-actions">Stores and Actions</h2>
91<p>First, let&#39;s create a store to keep track of our todo items. It will respond to the following actions:</p>
92<ul>
93<li><code>&quot;ADD_TODO&quot;</code> - adds a new todo</li>
94<li><code>&quot;TOGGLE_TODO&quot;</code> - completes or uncompletes a specific todo item</li>
95<li><code>&quot;CLEAR_TODOS&quot;</code> - removes all complete todo items</li>
96</ul>
97<pre><code class="lang-javascript"><span class="keyword">var</span> constants = {
98  ADD_TODO: <span class="string">"ADD_TODO"</span>,
99  TOGGLE_TODO: <span class="string">"TOGGLE_TODO"</span>,
100  CLEAR_TODOS: <span class="string">"CLEAR_TODOS"</span>
101};
102
103<span class="keyword">var</span> TodoStore = Fluxxor.createStore({
104  initialize: <span class="function"><span class="keyword">function</span>(<span class="params"></span>
104) </span>{
105    <span class="keyword">this</span>.todoId = <span class="number">0</span>;
106    <span class="keyword">this</span>.todos = {};
107
108    <span class="keyword">this</span>.bindActions(
109      constants.ADD_TODO, <span class="keyword">this</span>.onAddTodo,
110      constants.TOGGLE_TODO, <span class="keyword">this</span>.onToggleTodo,
111      constants.CLEAR_TODOS, <span class="keyword">this</span>.onClearTodos
112    );
113  },
114
115  onAddTodo: <span class="function"><span class="keyword">function</span>(<span class="params">payload</span>) </span>{
116    <span class="keyword">var</span> id = <span class="keyword">this</span>._nextTodoId();
117    <span class="keyword">var</span> todo = {
118      id: id,
119      text: payload.text,
120      complete: <span class="literal">false</span>
121    };
122    <span class="keyword">this</span>.todos[id] = todo;
123    <span class="keyword">this</span>.emit(<span class="string">"change"</span>);
124  },
125
126  onToggleTodo: <span class="function"><span class="keyword">function</span>(<span class="params">payload</span>
126) </span>{
127    <span class="keyword">var</span> id = payload.id;
128    <span class="keyword">this</span>.todos[id].complete = !<span class="keyword">this</span>.todos[id].complete;
129    <span class="keyword">this</span>.emit(<span class="string">"change"</span>);
130  },
131
132  onClearTodos: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{
133    <span class="keyword">var</span> todos = <span class="keyword">this</span>.todos;
134
135    <span class="built_in">Object</span>.keys(todos).forEach(<span class="function"><span class="keyword">function</span>(<span class="params">key</span>) </span>{
136      <span class="keyword">if</span>(todos[key].complete) {
137        <span class="keyword">delete</span> todos[key];
138      }
139    });
140
141    <span class="keyword">this</span>.emit(<span class="string">"change"</span>);
142  },
143
144  getState: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{
145    <span class="keyword">return</span> {
146      todos: <span class="keyword">this</span>.todos
147    };
148  },
149
150  _nextTodoId: <span class="function"><span class="keyword">function</span>(<span class="params"></span>
150) </span>{
151    <span class="keyword">return</span> ++<span class="keyword">this</span>.todoId;
152  }
153});
154</code></pre>
155<p>Let&#39;s create a few semantic actions to go along with our action types.</p>
156<pre><code class="lang-javascript"><span class="keyword">var</span> actions = {
157  addTodo: <span class="function"><span class="keyword">function</span>(<span class="params">text</span>) </span>{
158    <span class="keyword">this</span>.dispatch(constants.ADD_TODO, {text: text});
159  },
160
161  toggleTodo: <span class="function"><span class="keyword">function</span>(<span class="params">id</span>) </span>{
162    <span class="keyword">this</span>.dispatch(constants.TOGGLE_TODO, {id: id});
163  },
164
165  clearTodos: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{
166    <span class="keyword">this</span>.dispatch(constants.CLEAR_TODOS);
167  }
168};
169</code></pre>
170<p>Now we can instantiate our store and build a <code>Flux</code> instance:</p>
171<pre><code class="lang-javascript"><span class="keyword">var</span> stores = {
172  TodoStore: <span class="keyword">new</span> TodoStore()
173};
174
175<span class="keyword">var</span> flux = <span class="keyword">new</span> Fluxxor.Flux(stores, actions);
176</code></pre>
177<p>Finally, let&#39;s use the <code>&quot;dispatch&quot;</code> event to add some logging:</p>
178<pre><code class="lang-javascript">flux.on(<span class="string">"dispatch"</span>, <span class="function"><span class="keyword">function</span>(<span class="params">type, payload</span>
178) </span>{
179  <span class="keyword">if</span> (<span class="built_in">console</span> &amp;&amp; <span class="built_in">console</span>.log) {
180    <span class="built_in">console</span>.log(<span class="string">"[Dispatch]"</span>, type, payload);
181  }
182});
183</code></pre>
184<h2 id="react-application">React Application</h2>
185<p>Let&#39;s build out our UI with React.</p>
186<p>Our top-level <code>Application</code> component will use the <a href="/documentation/flux-mixin.html">FluxMixin</a> as well as the <a href="/documentation/store-watch-mixin.html">StoreWatchMixin</a> to make our lives a bit easier. The component will iterate over the array of todos and emit a <code>TodoItem</code> component for each one.</p>
187<p>We&#39;ll also add a quick form for adding new todo items, and a button for clearing completed todos.</p>
188<pre><code class="lang-javascript">var FluxMixin = Fluxxor.FluxMixin(React),
189    StoreWatchMixin = Fluxxor.StoreWatchMixin;
190
191var Application = React.createClass({
192  mixins: [FluxMixin, StoreWatchMixin("TodoStore")],
193
194  getInitialState: function() {
195    return { newTodoText: "" };
196  },
197
198  getStateFromFlux: function() {
199    var flux = this.getFlux();
200    // Our entire state is made up of the TodoStore data. In a larger
201    // application, you will likely return data from multiple stores, e.g.:
202    //
203    //   return {
204    //     todoData: flux.store("TodoStore").getState(),
205    //     userData: flux.store("UserStore").getData(),
206    //     fooBarData: flux.store("FooBarStore").someMoreData()
207    //   };
208    return flux.store("TodoStore").getState();
209  },
210
211  render: function() {
212    var todos = this.state.todos;
213    return (
214      &lt;div&gt;
215        &lt;ul&gt;
216          {Object.keys(todos).map(function(id) {
217            return &lt;li key={id}&gt;&lt;TodoItem todo={todos[id]} /&gt;&lt;/li&gt;;
218          })}
219        &lt;/ul&gt;
220        &lt;form onSubmit={this.onSubmitForm}&gt;
221          &lt;input type="text" size="30" placeholder="New Todo"
222                 value={this.state.newTodoText}
223                 onChange={this.handleTodoTextChange} /&gt;
224          &lt;input type="submit" value="Add Todo" /&gt;
225        &lt;/form&gt;
226        &lt;button onClick={this.clearCompletedTodos}&gt;Clear Completed&lt;/button&gt;
227      &lt;/div&gt;
228    );
229  },
230
231  handleTodoTextChange: function(e) {
232    this.setState({newTodoText: e.target.value});
233  },
234
235  onSubmitForm: function(e) {
236    e.preventDefault();
237    if (this.state.newTodoText.trim()) {
238      this.getFlux().actions.addTodo(this.state.newTodoText);
239      this.setState({newTodoText: ""});
240    }
241  },
242
243  clearCompletedTodos: function(e) {
244    this.getFlux().actions.clearTodos();
245  }
246});
247</code></pre>
248<p>The <code>TodoItem</code> component will display and style itself based on the completion of the todo, and will dispatch an action indicating its intent to toggle its completion state.</p>
249<pre><code class="lang-javascript"><span class="keyword">var</span> TodoItem = React.createClass({
250  mixins: [FluxMixin],
251
252  propTypes: {
253    todo: React.PropTypes.object.isRequired
254  },
255
256  render: <span class="function"><span class="keyword">function</span>(<span class="params"></span>
256) </span>{
257    <span class="keyword">var</span> style = {
258      textDecoration: <span class="keyword">this</span>.props.todo.complete ? <span class="string">"line-through"</span> : <span class="string">""</span>
259    };
260
261    <span class="keyword">return</span> <span class="xml"><span class="tag">&lt;<span class="title">span</span> <span class="attribute">style</span>=<span class="value">{style}</span> <span class="attribute">onClick</span>=<span class="value">{this.onClick}</span>&gt;</span>{this.props.todo.text}<span class="tag">&lt;/<span class="title">span</span>&gt;</span>;</span>
262  },
263
264  onClick: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{
265    <span class="keyword">this</span>.getFlux().actions.toggleTodo(<span class="keyword">this</span>.props.todo.id);
266  }
267});
268</code></pre>
269<h2 id="bringing-it-together">Bringing it Together</h2>
270<p>Now that we have a <code>Flux</code> instance and all our components are defined, we can finally render our app. We&#39;ll put it inside a <code>div</code> in our HTML with an ID of &quot;app&quot;.</p>
271<pre><code class="lang-javascript">React.render(<span class="xml"><span class="tag">&lt;<span class="title">Application</span> <span class="attribute">flux</span>=<span class="value">{flux}</span> /&gt;</span>, document.getElementById("app"));</span>
272</code></pre>
273<p>And that&#39;s it! We&#39;ve created a (super simple) Flux application with React and Fluxxor. You can find the full source code <a href="https://github.com/BinaryMuse/fluxxor/tree/master/examples/todo-basic">on GitHub</a>.</p>
274<script src="todo-bundle.js"></script>
274
275
276    <hr>
277    See a typo? Something still not clear?
278    <a href="https://github.com/BinaryMuse/fluxxor/issues/new">Report an issue on GitHub</a>.
279  </section>
280
281  <div class="footer-info">
282    <hr>
283    <p>Copyright &copy; 2014 <a href="https://github.com/BinaryMuse/">Michelle Tilley</a><br>
284    Licensed under <a href="http://opensource.org/licenses/MIT">the MIT license</a><br>
285    <a href="https://github.com/BinaryMuse/fluxxor">Available on GitHub</a></p>
286  </div>
287</div>
288
289<script>
290document.querySelectorAll(".show-nav")[0].addEventListener("click", function(ev) {
291  ev.preventDefault();
292  document.querySelectorAll(".nav-list")[0].style.display = 'block';
293  document.querySelectorAll(".show-nav")[0].style.display = 'none';
294  document.querySelectorAll(".hide-nav")[0].style.display = 'block';
295});
296
297document.querySelectorAll(".hide-nav")[0].addEventListener("click", function(ev) {
298  ev.preventDefault();
299  document.querySelectorAll(".nav-list")[0].style.display = 'none';
300  document.querySelectorAll(".show-nav")[0].style.display = 'block';
301  document.querySelectorAll(".hide-nav")[0].style.display = 'none';
302});
303</script>
303
304
305<script>
vendor: 339 bytes, lines 305-311
305
306  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
307  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
308  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
309  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
310
311  ga('create', '
311UA-51086297-1
vendor: 21 bytes, lines 311-312
311', 'fluxxor.com');
312  
312ga('require', 'displayfeatures');
313  ga('require', 'linkid', 'linkid.js');
314  ga('send', 'pageview');
315</script>
vendor: 1 bytes, line 315
315
316<script>
317  function appendAnchorSymbol(el, id) {
318    var anchor = document.createElement("a");
319    anchor.setAttribute("href", "#" + id);
320    anchor.setAttribute("class", "anchor-symbol");
321    anchor.innerHTML = "&para;";
322    el.appendChild(anchor);
323  }
324
325  var hs = document.querySelectorAll("h1,h2,h3,h4,h5,h6"),
326      h, id;
327  for (var i = 0; i < hs.length; i++) {
328    h = hs[i];
329    id = h.getAttribute("id");
330    if (id) {
331      appendAnchorSymbol(h, id);
332    }
333  }
334</script>
334
335
336</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.