<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Mark&#39;s Dev Blog</title>
    <link>https://blog.isquaredsoftware.com/series/practical-redux/index.xml</link>
    <description>Recent content on Mark&#39;s Dev Blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <atom:link href="https://blog.isquaredsoftware.com/series/practical-redux/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Practical Redux, Part 11: Nested Data and Trees</title>
      <link>https://blog.isquaredsoftware.com/2018/01/practical-redux-part-11-nested-data-trees/</link>
      <pubDate>Mon, 01 Jan 2018 16:46:44 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2018/01/practical-redux-part-11-nested-data-trees/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/2017/07/practical-redux-part-10-managing-modals/&#34;&gt;Last time in Part 10&lt;/a&gt;&lt;/strong&gt;, we built modal dialog and context menu systems that were driven by Redux.  This time, we&#39;re going to &lt;strong&gt;add creation of new entities, implement loading of nested relational data, and display that nested data in a tree component&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The code for this project is on Github at &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek&#34;&gt;github.com/markerikson/project-minimek&lt;/a&gt;&lt;/strong&gt;.  The original WIP commits I made for this post can be seen in &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/14&#34;&gt;PR #14: Practical Redux Part 11 WIP&lt;/a&gt;&lt;/strong&gt;, and the final &amp;quot;clean&amp;quot; commits can be seen in in &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/15&#34;&gt;PR #15: Practical Redux Part 11 Final&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I&#39;ll be linking to each &amp;quot;final&amp;quot; commit as I go through the post, as well as specific files in those commits.  I won&#39;t paste every changed file in here or show every single changed line, to save space, but rather try to show the most relevant changes for each commit as appropriate.&lt;/p&gt;

&lt;h3 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#library-updates&#34;&gt;Library Updates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#adding-new-pilots&#34;&gt;Adding New Pilots&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#reorganizing-the-unit-info-display&#34;&gt;Reorganizing the Unit Info Display&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#loading-nested-unit-data&#34;&gt;Loading Nested Unit Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#displaying-unit-data-as-a-tree&#34;&gt;Displaying Unit Data as a Tree&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#final-thoughts&#34;&gt;Final Thoughts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#further-information&#34;&gt;Further Information&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;library-updates&#34;&gt;Library Updates&lt;/h2&gt;

&lt;p&gt;It&#39;s been a few months since the last post, and both React and Semantic-UI-React have been updated.  At the time of this writing, the latest versions are React 16.2 and Semantic-UI-React 0.77.&lt;/p&gt;

&lt;p&gt;Right now, this project is on React 15.6.  Since our code currently compiles and runs with no warnings, we should be able to safely upgrade to React 16 just by updating our package versions.  The main concern would be making sure that our other libraries are also compatible with React 16.  Since we &lt;a href=&#34;https://blog.isquaredsoftware.com/2017/07/practical-redux-part-9-managing-dependencies/&#34;&gt;previously updated libraries that depended on PropTypes&lt;/a&gt;, that&#39;s not much of an issue here. The only other issue is our use of Portals for context menus.  There&#39;s a newer version of the &lt;code&gt;react-portal&lt;/code&gt; library that supports both React 15 and React 16&#39;s differing Portal APIs, so we&#39;ll update that as well.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;yarn upgrade react@16.2 react-dom@16.2 react-portal@4.1.2
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/415fc959aae4bfca11eb859e01c8f24e9463c6d5&#34;&gt;Commit 415fc95: Upgrade to React 16.2&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There&#39;s one small code tweak we need to make, which is changing &lt;code&gt;Portal&lt;/code&gt; to be a named import instead of a default import.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/11b7ef4f43db895310124cac660f4198e60d7005&#34;&gt;Commit 11b7ef4: Update React-Portal usage to match version 4.x&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We&#39;ll also upgrade Semantic-UI-React.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;yarn upgrade semantic-ui-react@0.77
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/6e1be797d60d206f513bd34ca757c57db71a0fc0&#34;&gt;Commit 6e1be79: Update Semantic-UI-React&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As a side note, I actually experienced some issues with Yarn&#39;s offline mirror feature doing these upgrades. When I upgraded React, the older package tarballs were correctly removed from the &lt;code&gt;./offline-mirror&lt;/code&gt; feature, but the new tarballs weren&#39;t added.  Even more oddly, the SUI-React tarball showed up correctly.  I eventually resolved this by running &lt;code&gt;yarn cache clean&lt;/code&gt;, then re-attempting the package updates.&lt;/p&gt;

&lt;h2 id=&#34;adding-new-pilots&#34;&gt;Adding New Pilots&lt;/h2&gt;

&lt;p&gt;So far, we have focused on interacting with the list of pilots.  &lt;strong&gt;&lt;em&gt;Project Mini-Mek&lt;/em&gt;&lt;/strong&gt; currently has the ability to show a list of pilots, update pilot entries, and delete pilots.  However, we&#39;re still missing a key capability: actually creating new pilot entries (the &#39;C&#39; in &amp;quot;CRUD&amp;quot;).&lt;/p&gt;

&lt;p&gt;We&#39;ll tackle that shortly, but first we&#39;ll do a bit of code cleanup related to the pilots feature.&lt;/p&gt;

&lt;h3 id=&#34;pilots-code-cleanup&#34;&gt;Pilots Code Cleanup&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt; form has some inputs that are in separate rows, but each only takes up a part of the row, leaving some empty space.  We can consolidate those into a couple combined rows.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/51377a707d0794e676b802ab1cfb95e3f6a50312&#34;&gt;Commit 51377a7: Rearrange PilotDetails form to be more compact&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/51377a707d0794e676b802ab1cfb95e3f6a50312/src/features/pilots/PilotDetails/PilotDetails.jsx&#34;&gt;features/pilots/PilotDetails/PilotDetails.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;+               &amp;lt;Form.Group&amp;gt;
                    &amp;lt;Form.Field
                        name=&amp;quot;rank&amp;quot;
                        label=&amp;quot;Rank&amp;quot;
-                       width={16}
+                       width={10}
                   &amp;lt;/Form.Field
// omit other input values and fields
+               &amp;lt;/Form.Group&amp;gt;
+              &amp;lt;Form.Group widths=&amp;quot;equal&amp;quot;&amp;gt;
                   &amp;lt;Form.Field
                        name=&amp;quot;gunnery&amp;quot;
                        label=&amp;quot;Gunnery&amp;quot;
                   &amp;lt;/Form.Field&amp;gt;
+              &amp;lt;/Form.Group&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This looks a bit nicer:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2018-01-practical-redux-part-11/pilot-details-form.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2018-01-practical-redux-part-11/pilot-details-form.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;Also, the current list of pilot ranks is hardcoded in the format that SUI-React&#39;s &lt;code&gt;Dropdown&lt;/code&gt; wants.  We can turn that into a simple constants array, and then derive the display data as needed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/02bd796893902ebc7208134735257101605d8e8e&#34;&gt;Commit 02bd796: Simplify pilot rank constant definition&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/02bd796893902ebc7208134735257101605d8e8e/src/features/pilots/pilotsConstants.js&#34;&gt;features/pilots/pilotsConstants.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;export const PILOT_EDIT_STOP = &amp;quot;PILOT_EDIT_STOP&amp;quot;;

+export const PILOT_RANKS = [
+   &amp;quot;Private&amp;quot;,
+   &amp;quot;Corporal&amp;quot;,
+   &amp;quot;Sergeant&amp;quot;,
+   &amp;quot;Lieutenant&amp;quot;,
+   &amp;quot;Captain&amp;quot;,
+   &amp;quot;Major&amp;quot;,
+   &amp;quot;Colonel&amp;quot;,
+];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/02bd796893902ebc7208134735257101605d8e8e/src/features/pilots/PilotDetails/PilotDetails.jsx&#34;&gt;features/pilots/PilotDetails/PilotDetails.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {selectCurrentPilot, selectIsEditingPilot} from &amp;quot;../pilotsSelectors&amp;quot;;
+import {PILOT_RANKS} from &amp;quot;../pilotsConstants&amp;quot;;

-const RANKS = [
-   {value: &amp;quot;Private&amp;quot;, text : &amp;quot;Private&amp;quot;},
-   {value: &amp;quot;Corporal&amp;quot;, text : &amp;quot;Corporal&amp;quot;},
-   {value: &amp;quot;Sergeant&amp;quot;, text : &amp;quot;Sergeant&amp;quot;},
-   {value: &amp;quot;Lieutenant&amp;quot;, text : &amp;quot;Lieutenant&amp;quot;},
-   {value: &amp;quot;Captain&amp;quot;, text : &amp;quot;Captain&amp;quot;},
-   {value: &amp;quot;Major&amp;quot;, text : &amp;quot;Major&amp;quot;},
-   {value: &amp;quot;Colonel&amp;quot;, text : &amp;quot;Colonel&amp;quot;},
-];
+const RANKS = PILOT_RANKS.map(rank =&amp;gt; ({value : rank, text : rank}));
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;creating-new-entities&#34;&gt;Creating New Entities&lt;/h3&gt;

&lt;p&gt;We currently have the ability to edit items, and our editing feature has generic actions and reducers for updating the contents of Redux-ORM entities with new values.  However, our editing feature is built around the assumption that there are existing items in the &lt;code&gt;state.entities&lt;/code&gt; &amp;quot;current values&amp;quot; slice, and that editing an item should copy that item from &lt;code&gt;state.entities&lt;/code&gt; to the &lt;code&gt;state.editingEntities&lt;/code&gt; &amp;quot;work-in-progress&amp;quot; slice.  That assumption no longer holds true for adding and editing new items - we can&#39;t copy them because they don&#39;t yet exist in the &lt;code&gt;entities&lt;/code&gt; slice.&lt;/p&gt;

&lt;p&gt;We need some additional support for creating new entities directly into the &lt;code&gt;editingEntities&lt;/code&gt; slice so that our edit actions can work on them.  In addition, our &amp;quot;save edits&amp;quot; logic also assumes that an item with that type and ID already exists in &lt;code&gt;entities&lt;/code&gt;, and tries to look up that &lt;code&gt;Model&lt;/code&gt; instance to apply the updates from the edited model.  We need to update the save logic to handle this case as well.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/1c8e64b3fc736938ba74071f12d9db49873d5680&#34;&gt;Commit 1c8e64b: Add ability to edit a new entity&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/1c8e64b3fc736938ba74071f12d9db49873d5680/src/features/editing/editingReducer.js&#34;&gt;features/editing/editingReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {
    EDIT_ITEM_EXISTING,
+   EDIT_ITEM_NEW,
    EDIT_ITEM_UPDATE,
    EDIT_ITEM_APPLY,
    EDIT_ITEM_STOP,
    EDIT_ITEM_RESET,
} from &amp;quot;./editingConstants&amp;quot;;

export function updateEditedEntity(sourceEntities, destinationEntities, payload) {
    // Start by reading our &amp;quot;work-in-progress&amp;quot; data
    const readSession = orm.session(sourceEntities);

    const {itemType, itemID} = payload;

    // Look up the model instance for the requested item
    const model = getModelByType(readSession, itemType, itemID);


    // We of course will be updating our &amp;quot;current&amp;quot; relational data
    let writeSession = orm.session(destinationEntities);

    const ModelClass = writeSession[itemType];

    if(ModelClass.hasId(itemID)) {
        // Look up the original Model instance for the top item
        const existingItem = ModelClass.withId(itemID);

        if(existingItem.updateFrom) {
            // Each model class should know how to properly update itself and its
            // relations from another model of the same type.  Ask the original model to
            // update itself based on the &amp;quot;work-in-progress&amp;quot; model. Redux-ORM will apply
            // those changes as we go, and update `session.state` immutably.
            existingItem.updateFrom(model);
        }
    }
+    else {
+        const itemContents = model.toJSON();
+        ModelClass.parse(itemContents);
+    }

    // Return the updated &amp;quot;current&amp;quot; relational data.
    return writeSession.state;
}

+export function editItemNew(state, payload) {
+   const editingEntities = selectEditingEntities(state);
+
+   const updatedEditingEntities = createEntity(editingEntities, payload);
+   return updateEditingEntitiesState(state, updatedEditingEntities);
+}

const editingFeatureReducer = createReducer({}, {
    [EDIT_ITEM_EXISTING] : editItemExisting,
+   [EDIT_ITEM_NEW] : editItemNew,
    [EDIT_ITEM_UPDATE] : editItemUpdate,
    [EDIT_ITEM_APPLY] : editItemApply,
    [EDIT_ITEM_STOP] : editItemStop,
    [EDIT_ITEM_RESET] : editItemReset,
});

export default editingFeatureReducer;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;EDIT_ITEM_NEW&lt;/code&gt; action payload will contain &lt;code&gt;{itemType, itemID, newItemAttributes}&lt;/code&gt;.  Because we&#39;ve been consistent about naming those fields in our other action types, the case reducer can reuse our existing helper methods for basic entity CRUD, which makes this easy to implement.&lt;/p&gt;

&lt;p&gt;Also, we already have the ability to parse in plain JSON representations of our model classes, and are using that as the transfer mechanism to copy values from &lt;code&gt;entities&lt;/code&gt; to &lt;code&gt;editedEntities&lt;/code&gt;.  We can easily add that logic in here so that saving new items creates them in &lt;code&gt;entities&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&#34;generating-new-pilot-entries&#34;&gt;Generating New Pilot Entries&lt;/h3&gt;

&lt;p&gt;The next step is to actually generate a new Pilot entry and dispatch &lt;code&gt;EDIT_ITEM_NEW&lt;/code&gt; with the plain JSON representation of that pilot entry.  This brings up several things we need to think about.&lt;/p&gt;

&lt;p&gt;First, we need to have unique IDs for each Pilot entry.  Thus far we&#39;ve simply used hardcoded integers in our sample data, but we&#39;re going to need to generate IDs ourselves here for a couple reasons.  Redux-ORM does have support for auto-incrementing numerical IDs based on the max ID value in a &amp;quot;table&amp;quot;, but that won&#39;t work with our editing approach - the &lt;code&gt;editingEntities.Pilots&lt;/code&gt; table would have no existing items, so it would likely give us a 0 or a 1 as the ID every time.  We could calculate the numerical ID based on the contents of &lt;code&gt;state.entities&lt;/code&gt;, but really, relying on the existing entries is not a great approach.  It&#39;s better if we actually generate unique IDs.&lt;/p&gt;

&lt;p&gt;However, this also has some problems.  Generating unique IDs involves use of random numbers.  While there&#39;s nothing preventing you from generating random numbers in a Redux reducer, doing so makes that reducer &amp;quot;impure&amp;quot;, and it will return inconsistent output.  &lt;strong&gt;A Redux reducer should never contain randomness - it should always be handled outside the reducer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For our purposes, we can handle this by generating new pilot IDs in our action creator.  If we needed to actually generate random numbers, there&#39;s a couple approaches you can use.  I won&#39;t cover those here, but see the posts &lt;a href=&#34;https://daveceddia.com/random-numbers-in-redux/&#34;&gt;Roll the Dice: Random Numbers in Redux&lt;/a&gt; and &lt;a href=&#34;https://blog.ohlman.io/random-in-redux-b6b9932ad061&#34;&gt;Random in Redux&lt;/a&gt; for solutions and examples.&lt;/p&gt;

&lt;p&gt;Another big question is where the logic for default model attribute values should live, and how to override those defaults when a new model instance is created.  I&#39;ve chosen to define a plain object of attributes in the same file as the model class, add a static &lt;code&gt;generate()&lt;/code&gt; function to the model class, and merge together the default attributes and any attributes provided by the caller.&lt;/p&gt;

&lt;p&gt;Finally, we&#39;re running into an issue with an optimization we applied earlier.  We have a memoized &lt;code&gt;getEntitiesSession&lt;/code&gt; selector that ensures we only create a single Redux-ORM &lt;code&gt;Session&lt;/code&gt; instance for each update to the &lt;code&gt;state.entities&lt;/code&gt; slice, just so we aren&#39;t creating separate &lt;code&gt;Session&lt;/code&gt; instances every time a connected component&#39;s &lt;code&gt;mapState&lt;/code&gt; function re-runs.  If we were to use that selector and get that &amp;quot;shared&amp;quot; &lt;code&gt;Session&lt;/code&gt; instance, then use that to generate a new &lt;code&gt;Pilot&lt;/code&gt; instance, the shared &lt;code&gt;Session&lt;/code&gt; would swap out its &lt;code&gt;session.state&lt;/code&gt; field with the updated data.  That could potentially cause problems, so we really want to avoid reusing that &lt;code&gt;Session&lt;/code&gt; in this process.  My solution is to create a &lt;code&gt;getUnsharedEntitiesSession&lt;/code&gt; selector that just creates a new &lt;code&gt;Session&lt;/code&gt;, which can then be safely used for manipulating data instead of just reading values.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/0af9785c8e19ad7282956e550c83c6981c37d017&#34;&gt;Commit 0af9785: Implement logic to add and edit a new pilot&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/0af9785c8e19ad7282956e550c83c6981c37d017/src/features/entities/entitySelectors.js&#34;&gt;features/entities/entitySelectors.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;+export const getUnsharedEntitiesSession = (state) =&amp;gt; {
+   const entities = selectEntities(state);
+   return orm.session(entities);
+}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/0af9785c8e19ad7282956e550c83c6981c37d017/src/features/pilots/Pilot.js&#34;&gt;features/pilots/Pilot.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;+const defaultAttributes = {
+   name : &amp;quot;New Pilot&amp;quot;,
+   rank : &amp;quot;Private&amp;quot;,
+   gunnery : 4,
+   piloting : 5,
+   age : 25,
+};

export default class Pilot extends Model {
+   static generate(newAttributes = {}) {
+       const combinedAttributes = {
+           ...defaultAttributes,
+           ...newAttributes,
+       };
+
+       return this.create(combinedAttributes);
+   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/0af9785c8e19ad7282956e550c83c6981c37d017/src/features/pilots/pilotsActions.js&#34;&gt;features/pilots/pilotsActions.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;+import cuid from &amp;quot;cuid&amp;quot;;

import {
    editExistingItem,
+    editNewItem,
    applyItemEdits,
    stopEditingItem
} from &amp;quot;features/editing/editingActions&amp;quot;;

import {selectCurrentPilot, selectIsEditingPilot} from &amp;quot;./pilotsSelectors&amp;quot;;
+import {getUnsharedEntitiesSession} from &amp;quot;features/entities/entitySelectors&amp;quot;;

+export function addNewPilot() {
+   return (dispatch, getState) =&amp;gt; {
+       const session = getUnsharedEntitiesSession(getState());
+       const {Pilot} = session;
+
+       const id = cuid();
+
+       const newPilot = Pilot.generate({id});
+
+       const pilotContents = newPilot.toJSON();
+
+       dispatch(editNewItem(&amp;quot;Pilot&amp;quot;, id, pilotContents));
+       dispatch(selectPilot(id));
+       dispatch({type : PILOT_EDIT_START});
+   }
=}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Way back at the start of the series, we added the &lt;code&gt;cuid&lt;/code&gt; module for generating IDs.  We can finally make use of that here.&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;addNewPilot()&lt;/code&gt; thunk first creates a &lt;code&gt;Session&lt;/code&gt; instance we can use for modifying data.  We generate a new ID value, then pass the ID as a field to &lt;code&gt;Pilot.generate()&lt;/code&gt;, which returns a &lt;code&gt;Pilot&lt;/code&gt; instance.  We can serialize that to a plain JS object, and dispatch the actions to edit the item, mark it as selected, and update our state to reflect that we&#39;re currently editing a pilot.&lt;/p&gt;

&lt;h3 id=&#34;pilot-form-updates&#34;&gt;Pilot Form Updates&lt;/h3&gt;

&lt;p&gt;With the logic in place, we need to actually add some UI to call &lt;code&gt;addNewPilot()&lt;/code&gt;.  We&#39;ll add a new section below the &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt; form with a button that lets us add and start editing a new pilot.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/179cc525e699d2bab803c9a0d96d4c68786a29f1&#34;&gt;Commit 179cc52: Add an &amp;quot;Add New Pilot&amp;quot; button&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/179cc525e699d2bab803c9a0d96d4c68786a29f1/src/features/pilots/PilotDetails/PilotCommands.jsx&#34;&gt;features/pilots/PilotDetails/PilotCommands.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import React from &amp;quot;react&amp;quot;;
import {connect} from &amp;quot;react-redux&amp;quot;;
import {Button} from &amp;quot;semantic-ui-react&amp;quot;;

import {selectIsEditingPilot} from &amp;quot;../pilotsSelectors&amp;quot;;
import {addNewPilot} from &amp;quot;../pilotsActions&amp;quot;;

const mapState = (state) =&amp;gt; {
    const isEditingPilot = selectIsEditingPilot(state);

    return {isEditingPilot};
}

const buttonWidth = 140;

const actions = {addNewPilot};

const PilotCommands = (props) =&amp;gt; (
    &amp;lt;Button
        primary
        disabled={props.isEditingPilot}
        type=&amp;quot;button&amp;quot;
        onClick={props.addNewPilot}
        style={{width : buttonWidth, marginRight : 10}}
    &amp;gt;
        Add New Pilot
    &amp;lt;/Button&amp;gt;
);

export default connect(mapState, actions)(PilotCommands);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/179cc525e699d2bab803c9a0d96d4c68786a29f1/src/features/pilots/Pilots/Pilots.jsx&#34;&gt;features/pilots/Pilots/Pilots.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import PilotsList from &amp;quot;../PilotsList&amp;quot;;
import PilotDetails from &amp;quot;../PilotDetails&amp;quot;;
+import PilotCommands from &amp;quot;../PilotDetails/PilotCommands&amp;quot;;


export default class Pilots extends Component {
    render() {
    // skip other rendering code
                         &amp;lt;Segment &amp;gt;
                            &amp;lt;PilotDetails /&amp;gt;
                        &amp;lt;/Segment&amp;gt;
+                       &amp;lt;Segment&amp;gt;
+                           &amp;lt;PilotCommands /&amp;gt;
+                       &amp;lt;/Segment&amp;gt;
                    &amp;lt;/Grid.Column&amp;gt;
                &amp;lt;/Grid&amp;gt;
            &amp;lt;/Segment&amp;gt;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now we can hit &amp;quot;Add New Pilot&amp;quot;, edit the details, save the edits, and see the pilot added to the list:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2018-01-practical-redux-part-11/new-pilot-added.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2018-01-practical-redux-part-11/new-pilot-added.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;h3 id=&#34;fixing-pilot-selection-logic&#34;&gt;Fixing Pilot Selection Logic&lt;/h3&gt;

&lt;p&gt;There&#39;s one issue left from the current code.  If we click &amp;quot;Add New Pilot&amp;quot; and then click &amp;quot;Cancel Edits&amp;quot;, the &amp;quot;Start Editing&amp;quot; button is still enabled.  This is because we still have &lt;code&gt;state.pilots.selectedPilot&lt;/code&gt; set to the ID of the generated pilot and that isn&#39;t getting cleared out when we hit Cancel, so it thinks a valid pilot is still selected.  We really need to clear the selection if we&#39;re canceling the edit.&lt;/p&gt;

&lt;p&gt;There&#39;s probably a few ways we could handle this.  For now, we&#39;ll implement the behavior on the action creation side, by checking to see if it&#39;s a new pilot when we stop editing.&lt;/p&gt;

&lt;p&gt;In addition, the logic for the &lt;code&gt;stopEditingPilot()&lt;/code&gt; and &lt;code&gt;cancelEditingPilot()&lt;/code&gt; thunks is looking pretty similar.  We can consolidate that logic into a single function with a flag that indicates whether we should apply the edits or not.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/8ceeece28aa08abe84f12264626afb0b5a807e0e&#34;&gt;Commit 8ceeece: Extract common &amp;quot;stop editing pilot&amp;quot; logic&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/8ceeece28aa08abe84f12264626afb0b5a807e0e/src/features/pilots/pilotsActions.js&#34;&gt;features/pilots/pilotsActions.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;
import {selectCurrentPilot, selectIsEditingPilot} from &amp;quot;./pilotsSelectors&amp;quot;;
-import {getUnsharedEntitiesSession} from &amp;quot;features/entities/entitySelectors&amp;quot;;
import {getEntitiesSession, getUnsharedEntitiesSession} from &amp;quot;features/entities/entitySelectors&amp;quot;;

+export function handleStopEditingPilot(applyEdits = true) {
+   return (dispatch, getState) =&amp;gt; {
+       const currentPilot = selectCurrentPilot(getState());
+
+       // Determine if it&#39;s a new pilot based on the &amp;quot;current&amp;quot; slice contents
+       const session = getEntitiesSession(getState());
+       const {Pilot} = session;
+
+       const isNewPilot = !Pilot.hasId(currentPilot);
+
+       dispatch({type : PILOT_EDIT_STOP});
+
+       if(applyEdits) {
+           dispatch(applyItemEdits(&amp;quot;Pilot&amp;quot;, currentPilot));
+       }
+
+       dispatch(stopEditingItem(&amp;quot;Pilot&amp;quot;, currentPilot));
+
+       if(isNewPilot) {
+           dispatch({type : PILOT_SELECT, payload : {currentPilot : null}});
+       }
+   }
+}


export function stopEditingPilot() {
    return (dispatch, getState) =&amp;gt; {
-       const currentPilot = selectCurrentPilot(getState());
-
-       dispatch({type : PILOT_EDIT_STOP});
-       dispatch(applyItemEdits(&amp;quot;Pilot&amp;quot;, currentPilot));
-       dispatch(stopEditingItem(&amp;quot;Pilot&amp;quot;, currentPilot));
+       dispatch(handleStopEditingPilot(true));
    }
}

export function cancelEditingPilot() {
    return (dispatch, getState) =&amp;gt; {
-       const currentPilot = selectCurrentPilot(getState());
-
-        dispatch({type : PILOT_EDIT_STOP});
-        dispatch(stopEditingItem(&amp;quot;Pilot&amp;quot;, currentPilot));
+        dispatch(handleStopEditingPilot(false));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can determine if it&#39;s a new pilot by seeing whether the &lt;code&gt;currentPilot&lt;/code&gt; ID value actually exists in the &amp;quot;current&amp;quot; &lt;code&gt;Pilot&lt;/code&gt; table.  From there, we clear out the &amp;quot;editing pilot&amp;quot; flag, save the edits if appropriate, clear out the entry from the &amp;quot;editing&amp;quot; slice, and clear the selection if necessary.&lt;/p&gt;

&lt;h2 id=&#34;reorganizing-the-unit-info-display&#34;&gt;Reorganizing the Unit Info Display&lt;/h2&gt;

&lt;p&gt;Most of our work so far has focused on the &amp;quot;Pilots&amp;quot; tab, although we&#39;ve worked some on the &amp;quot;Unit Info&amp;quot; and &amp;quot;Mechs&amp;quot; tabs.  Meanwhile, the &amp;quot;Unit Organization&amp;quot; tab has been left alone since we put together the initial layout.  In preparation for our next major chunk of feature work, we&#39;re going to consolidate things by moving the tree from the &amp;quot;Unit Organization&amp;quot; tab into our main &amp;quot;Unit Info&amp;quot; tab.&lt;/p&gt;

&lt;p&gt;We&#39;ll start by extracting a separate &lt;code&gt;&amp;lt;UnitInfoForm&amp;gt;&lt;/code&gt; component from the existing &lt;code&gt;&amp;lt;UnitInfo&amp;gt;&lt;/code&gt; panel.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/d2ac9f6b52c66fa8e01a7e007156c238dc2c9fc8&#34;&gt;Commit d2ac9f6: Extract a separate UnitInfoForm component&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/d2ac9f6b52c66fa8e01a7e007156c238dc2c9fc8/src/features/unitInfo/UnitInfo/UnitInfo.jsx&#34;&gt;features/unitInfo/UnitInfo/UnitInfo.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import React, {Component} from &amp;quot;react&amp;quot;;
import {
    Segment
} from &amp;quot;semantic-ui-react&amp;quot;;

import UnitInfoForm from &amp;quot;./UnitInfoForm&amp;quot;;

class UnitInfo extends Component {

    render() {
        return (
            &amp;lt;Segment attached=&amp;quot;bottom&amp;quot;&amp;gt;
                &amp;lt;UnitInfoForm /&amp;gt;
            &amp;lt;/Segment&amp;gt;
        );
    }
}

export default UnitInfo;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Code-wise, this was really more like renaming &lt;code&gt;UnitInfo.jsx&lt;/code&gt; to &lt;code&gt;UnitInfoForm.jsx&lt;/code&gt;, removing a couple of components from its render method, and then creating a new &lt;code&gt;UnitInfo.jsx&lt;/code&gt; file to replace it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/0ec6f087c2b8f88e558d11fd4bd5419a10fc5b46&#34;&gt;Commit 0ec6f08: Move UnitOrganization under UnitInfo and remove unused tab&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/0ec6f087c2b8f88e558d11fd4bd5419a10fc5b46/src/app/layout/App.js&#34;&gt;app/layout/App.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import UnitInfo from &amp;quot;features/unitInfo/UnitInfo&amp;quot;;
import Pilots from &amp;quot;features/pilots/Pilots&amp;quot;;
import Mechs from &amp;quot;features/mechs/Mechs&amp;quot;;
-import UnitOrganization from &amp;quot;features/unitOrganization/UnitOrganization&amp;quot;;
import Tools from &amp;quot;features/tools/Tools&amp;quot;;
import ModalManager from &amp;quot;features/modals/ModalManager&amp;quot;;

class App extends Component {
    render() {
        const tabs = [
            {name : &amp;quot;unitInfo&amp;quot;, label : &amp;quot;Unit Info&amp;quot;, component : UnitInfo,},
            {name : &amp;quot;pilots&amp;quot;, label : &amp;quot;Pilots&amp;quot;, component : Pilots,},
            {name : &amp;quot;mechs&amp;quot;, label : &amp;quot;Mechs&amp;quot;, component : Mechs,},
-           {name : &amp;quot;unitOrganization&amp;quot;, label : &amp;quot;Unit Organization&amp;quot;, component : UnitOrganization},
            {name : &amp;quot;tools&amp;quot;, label : &amp;quot;Tools&amp;quot;, component : Tools},
        ];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next, we remove the &lt;code&gt;&amp;lt;UnitOrganization&amp;gt;&lt;/code&gt; component so it&#39;s no longer rendered as a separate tab, and move its file inside &lt;code&gt;features/unitInfo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then, we can show &lt;code&gt;&amp;lt;UnitOrganization&amp;gt;&lt;/code&gt; inside of the revamped &lt;code&gt;&amp;lt;UnitInfo&amp;gt;&lt;/code&gt; panel:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/d18161b511a0312d22e3a634d4e66ec76c60d400&#34;&gt;Commit d18161b: Add UnitOrganization component to UnitInfo panel&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import React, {Component} from &amp;quot;react&amp;quot;;
import {
    Segment,
    Grid,
    Header,
} from &amp;quot;semantic-ui-react&amp;quot;;

import UnitOrganization from &amp;quot;../UnitOrganization&amp;quot;;
import UnitInfoForm from &amp;quot;./UnitInfoForm&amp;quot;;

class UnitInfo extends Component {
    render() {
        return (
            &amp;lt;Segment&amp;gt;
                &amp;lt;Grid&amp;gt;
                    &amp;lt;Grid.Column width={10}&amp;gt;
                        &amp;lt;Header as=&amp;quot;h3&amp;quot;&amp;gt;Unit Table of Organization&amp;lt;/Header&amp;gt;
                        &amp;lt;Segment&amp;gt;
                            &amp;lt;UnitOrganization /&amp;gt;
                        &amp;lt;/Segment&amp;gt;
                    &amp;lt;/Grid.Column&amp;gt;
                    &amp;lt;Grid.Column width={6}&amp;gt;
                        &amp;lt;Header as=&amp;quot;h3&amp;quot;&amp;gt;Edit Unit&amp;lt;/Header&amp;gt;
                        &amp;lt;Segment&amp;gt;
                            &amp;lt;UnitInfoForm /&amp;gt;
                        &amp;lt;/Segment&amp;gt;
                    &amp;lt;/Grid.Column&amp;gt;
                &amp;lt;/Grid&amp;gt;
            &amp;lt;/Segment&amp;gt;
        );
    }
}

export default UnitInfo;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We&#39;ll consolidate the &lt;code&gt;&amp;lt;UnitInfoForm&amp;gt;&lt;/code&gt; &amp;quot;Affiliation&amp;quot; and &amp;quot;Color&amp;quot; fields into one row, similar to what we did with the &lt;code&gt;&amp;lt;PilotDetailsForm&amp;gt;&lt;/code&gt; earlier.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/3c1be29b30c4b724656868bbe9bf1e4fd0a28082&#34;&gt;Commit 3c1be29: Improve UnitInfoForm layout&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And finally, we&#39;ll rename &lt;code&gt;&amp;lt;UnitOrganization&amp;gt;&lt;/code&gt; to &lt;code&gt;&amp;lt;UnitOrganizationTree&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/361a1aac335c6c84ceb9b3fe57266662442a4d6b&#34;&gt;Commit 361a1aa: Rename UnitOrganization to UnitOrganizationTree&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Note that since we&#39;ve started this project, &lt;code&gt;&amp;lt;UnitInfo&amp;gt;&lt;/code&gt; has gone from being unconnected, to connected, and is now unconnected again.  &lt;strong&gt;This is one of the reasons why I dislike specifically splitting code into &lt;code&gt;containers&lt;/code&gt; and &lt;code&gt;components&lt;/code&gt; folders, or having separate &lt;code&gt;SomeComponent&lt;/code&gt; and &lt;code&gt;SomeComponentContainer&lt;/code&gt; files - it&#39;s very possible that a component&#39;s usage could change over time.&lt;/strong&gt;  Now, I &lt;em&gt;will&lt;/em&gt; say that there&#39;s a difference between &amp;quot;app-specific&amp;quot; components and &lt;em&gt;truly&lt;/em&gt; generic components.  We do have a &lt;code&gt;common/components&lt;/code&gt; folder in this project, and it&#39;s very reasonable to put completely generic components in there.  But, for anything that&#39;s actually related to app concepts, I&#39;d rather put it in an appropriate feature folder and just keep it there, regardless of whether it&#39;s connected or not.  (I have &lt;a href=&#34;https://gist.github.com/markerikson/ea312b5ee398627ffceb09f89904831f&#34;&gt;a saved Reactiflux chat log where I discuss my thoughts on Redux &amp;quot;container&amp;quot; components and structuring&lt;/a&gt;.)&lt;/p&gt;

&lt;h2 id=&#34;loading-nested-unit-data&#34;&gt;Loading Nested Unit Data&lt;/h2&gt;

&lt;p&gt;Our data schema so far has been pretty simple.  The &lt;code&gt;sampleData.js&lt;/code&gt; file currently looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;const sampleData = {
    unit : {
        name : &amp;quot;Black Widow Company&amp;quot;,
        affiliation : &amp;quot;wd&amp;quot;,
        color : &amp;quot;black&amp;quot;
    },
    pilots : [
        {
            id : 1,
            name : &amp;quot;Natasha Kerensky&amp;quot;,
            rank : &amp;quot;Captain&amp;quot;,
            gunnery : 2,
            piloting : 2,
            age : 52,
            mech : 1,
        },
   ],
   designs : [
        {
            id : &amp;quot;STG-3R&amp;quot;,
            name : &amp;quot;Stinger&amp;quot;,
            weight : 20,
        },
   ],
   mechs : [
        {
            id : 1,
            type : &amp;quot;WHM-6R&amp;quot;,
            pilot : 1,
        },
   ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We&#39;ve got flat arrays for pilots, designs, and mechs, and we only have a single unit defined.  The arrays themselves already reference each other by foreign key IDs, so there&#39;s not much processing needed.&lt;/p&gt;

&lt;p&gt;It&#39;s time to start adding some additional depth to this schema.  As mentioned in &lt;a href=&#34;https://blog.isquaredsoftware.com/2016/10/practical-redux-part-0-introduction/&#34;&gt;Part 0&lt;/a&gt; and &lt;a href=&#34;https://blog.isquaredsoftware.com/2016/11/practical-redux-part-3-project-planning-and-setup/&#34;&gt;Part 3&lt;/a&gt;, in the Battletech game universe mechs are normally organized into &lt;a href=&#34;http://www.sarna.net/wiki/Inner_Sphere_Military_Structure#Lance&#34;&gt;&amp;quot;Lances&amp;quot; of 4 mechs, and &amp;quot;Companies&amp;quot; of 3 lances&lt;/a&gt;.  We&#39;re going to apply that organizational pattern to our current sample data.&lt;/p&gt;

&lt;p&gt;Long-term, it would make sense to support loading multiple units, and possibly having the pilots and mechs defined in a nested data tree that matches the organizational structure.  We&#39;re not going to go &lt;em&gt;quite&lt;/em&gt; that far yet.  For now, we&#39;re going to start treating the unit as another model type in our database, and store the &lt;code&gt;pilots&lt;/code&gt; and &lt;code&gt;mechs&lt;/code&gt; arrays inside of the unit definition.  We&#39;ll also add a &lt;code&gt;lances&lt;/code&gt; array that stores which pilots belong to which lances.  The &lt;code&gt;designs&lt;/code&gt; array will stay outside the &lt;code&gt;unit&lt;/code&gt; field in the data, because mech designs are universal across factions and not specific to a unit.&lt;/p&gt;

&lt;p&gt;This also means that we&#39;re going to need to make our &amp;quot;parsing&amp;quot; logic a bit more complex, because it will need to handle the now-nested data correctly.&lt;/p&gt;

&lt;h3 id=&#34;parsing-unit-entries&#34;&gt;Parsing Unit Entries&lt;/h3&gt;

&lt;p&gt;The first step is to create our &lt;code&gt;Unit&lt;/code&gt; model.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/87a5f9e6826df2bd12ce83a1d0a1ff831860b47c&#34;&gt;Commit 87a5f9e: Add a Unit model class&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/87a5f9e6826df2bd12ce83a1d0a1ff831860b47c/src/features/unitInfo/Unit.js&#34;&gt;features/unitInfo/Unit.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {Model, many, attr} from &amp;quot;redux-orm&amp;quot;;

export default class Unit extends Model {
    static modelName = &amp;quot;Unit&amp;quot;;

    static fields = {
        id : attr(),
        name : attr(),
        affiliation : attr(),
        color : attr(),
        pilots : many(&amp;quot;Pilot&amp;quot;),
        mechs : many(&amp;quot;Mech&amp;quot;)
    };

    static parse(unitData) {
        const {Pilot, Mech} = this.session;

        const parsedData = {
            ...unitData,
            pilots : unitData.pilots.map(pilotEntry =&amp;gt; Pilot.parse(pilotEntry)),
            mechs : unitData.mechs.map(mechEntry =&amp;gt; Mech.parse(mechEntry)),
        };

        return this.upsert(parsedData);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There&#39;s a few things to note in this file.&lt;/p&gt;

&lt;p&gt;First, for other model classes so far, I&#39;ve tended to write the &lt;code&gt;fields&lt;/code&gt; definition as &lt;code&gt;static get fields() {}&lt;/code&gt;, and usually defined the &lt;code&gt;modelName&lt;/code&gt; field separately, like &lt;code&gt;Pilot.modelName = &amp;quot;Pilot&amp;quot;;&lt;/code&gt;.  This is somewhat for historical reasons - I first began using Redux-ORM before I had the Class Properties syntax available in my project, so I used getters and plain assignments instead.  In theory, all three of these &lt;em&gt;should&lt;/em&gt; be equivalent:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;// 1) Field declarations added to the class later
class Pilot extends Model {}
Pilot.fields = {
  id : attr()
};

// 2) Static getters
class Pilot extends Model {
    static get fields() {
        return {
            id : attr()
        };
    }
}

// 3) The Stage 3 Class Properties syntax
class Pilot extends Model {
    static fields = {
        id : attr()
    };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Going forward, I&#39;ll stick with the Class Properties syntax, and define &lt;code&gt;fields&lt;/code&gt; and &lt;code&gt;modelName&lt;/code&gt; inside the class body.&lt;/p&gt;

&lt;p&gt;Next, for the first time we&#39;re using Redux-ORM&#39;s &lt;code&gt;many()&lt;/code&gt; relation.  This will set up &amp;quot;through tables&amp;quot; that map together the related IDs from both tables.  In this case, we&#39;ll have auto-generated model types called &lt;code&gt;UnitPilots&lt;/code&gt; and &lt;code&gt;UnitMechs&lt;/code&gt;, and a sample &lt;code&gt;UnitPilots&lt;/code&gt; entry might look like &lt;code&gt;{id : 2, fromUnitId : 1, toPilotId : 3}&lt;/code&gt;.  If we have an instance of a &lt;code&gt;Unit&lt;/code&gt;, the &lt;code&gt;unitModel.pilots&lt;/code&gt; field will be a Redux-ORM &lt;code&gt;QuerySet&lt;/code&gt; that can be turned into an array of &lt;code&gt;Pilot&lt;/code&gt; models or plain JS objects.&lt;/p&gt;

&lt;p&gt;Finally, notice that the &lt;code&gt;Unit.parse()&lt;/code&gt; method is more complicated than the others we&#39;ve seen thus far.  Since our other classes haven&#39;t had to deal with any nesting, our other &lt;code&gt;parse()&lt;/code&gt; methods have just looked like &lt;code&gt;return this.create(data)&lt;/code&gt; or &lt;code&gt;return this.upsert(data)&lt;/code&gt;.  Now, we need to continue recursing down through the nested data to parse any &lt;code&gt;Pilot&lt;/code&gt; or &lt;code&gt;Mech&lt;/code&gt; entries.&lt;/p&gt;

&lt;p&gt;Our data loading reducer already runs &lt;code&gt;pilots.map(pilotEntry =&amp;gt; Pilot.parse(pilotEntry))&lt;/code&gt;, and the same for mechs.  We can do that here instead, but there&#39;s a bit of a trick involved.  Redux-ORM creates custom subclasses of your model classes every time you instantiate a &lt;code&gt;Session&lt;/code&gt;.  Those subclasses are attached to the &lt;code&gt;Session&lt;/code&gt; instance, and any operations involving those subclasses are applied to that specific &lt;code&gt;Session&lt;/code&gt;.  So, we can&#39;t just do &lt;code&gt;import Pilot from &amp;quot;features/pilots/Pilot&amp;quot;&lt;/code&gt; here - we need to get a reference to the specific &lt;code&gt;Pilot&lt;/code&gt; subclass on the current &lt;code&gt;Session&lt;/code&gt; instance related to where &lt;code&gt;Unit.parse()&lt;/code&gt; is being called.&lt;/p&gt;

&lt;p&gt;Fortunately, the actual solution is pretty easy.  When this code runs, &lt;code&gt;this&lt;/code&gt; inside the static method will refer to the &lt;code&gt;Session&lt;/code&gt;-specific subclass of &lt;code&gt;Unit&lt;/code&gt;, and Redux-ORM makes the &lt;code&gt;Session&lt;/code&gt; available as &lt;code&gt;this.session&lt;/code&gt;.  So, in the same way that we did &lt;code&gt;const {Pilot} = session&lt;/code&gt; over in the reducer, we can do &lt;code&gt;const {Pilot} = this.session&lt;/code&gt; here inside the static class method.&lt;/p&gt;

&lt;p&gt;From there, we call &lt;code&gt;Pilot.parse()&lt;/code&gt; and &lt;code&gt;Mech.parse()&lt;/code&gt; as we map over the arrays.  Those create the proper entries inside the &lt;code&gt;Session&lt;/code&gt;, and then passing those newly-created model entries into &lt;code&gt;this.upsert()&lt;/code&gt; instead of the original plain objects will tell Redux-ORM to set up the associations between the &lt;code&gt;Unit&lt;/code&gt; and those related models.&lt;/p&gt;

&lt;p&gt;With that done, we can restructure the sample data to match:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/58b9115df6f2fa34dbef75d5788aeead80ac5a39&#34;&gt;Commit 58b9115: Restructure sample data to include pilots/mechs inside unit definition&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And then we need to update the data loading reducer to call &lt;code&gt;Unit.parse()&lt;/code&gt; instead of parsing the individual pilots and mechs directly:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/c8cabf2bdc9c3a255e4f4081b177cf3fe84bf768&#34;&gt;Commit c8cabf2: Update data loading reducer to parse nested unit definition&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/c8cabf2bdc9c3a255e4f4081b177cf3fe84bf768/src/app/reducers/entitiesReducer.js&#34;&gt;app/reducers/entitiesReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;export function loadData(state, payload) {
    // Create a Redux-ORM session from our entities &amp;quot;tables&amp;quot;
    const session = orm.session(state);
    // Get a reference to the correct version of model classes for this Session
-   const {Pilot, MechDesign, Mech} = session;
+   const {Unit, Pilot, Mech, MechDesign} = session;

-   const {pilots, designs, mechs} = payload;
+   const {unit, designs} = payload;

    // Clear out any existing models from state so that we can avoid
    // conflicts from the new data coming in if data is reloaded
-   [Pilot, Mech, MechDesign].forEach(modelType =&amp;gt; {
+   [Unit, Pilot, Mech, MechDesign].forEach(modelType =&amp;gt; {
        modelType.all().toModelArray().forEach(model =&amp;gt; model.delete());
    });

    // Immutably update the session state as we insert items
+    Unit.parse(unit);
-    pilots.forEach(pilot =&amp;gt; Pilot.parse(pilot));

    designs.forEach(design =&amp;gt; MechDesign.parse(design));
-    mechs.forEach(mech =&amp;gt; Mech.parse(mech));

    // Return the new &amp;quot;tables&amp;quot; object containing the updates
    return session.state;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;extracting-factions&#34;&gt;Extracting Factions&lt;/h3&gt;

&lt;p&gt;The list of factions in the &amp;quot;Affiliation&amp;quot; dropdown is currently hardcoded, and also in a format specific to the SUI-React &lt;code&gt;&amp;lt;Dropdown&amp;gt;&lt;/code&gt; component.  We can turn those into a &lt;code&gt;Faction&lt;/code&gt; model and extract those from the &lt;code&gt;&amp;lt;UnitInfoForm&amp;gt;&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;First, we&#39;ll create the model class and the sample data, then update the data loading reducer to parse in the &lt;code&gt;Faction&lt;/code&gt; entries.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/29eb97b0f341a5bdfa12d6a21511be9e48821801&#34;&gt;Commit 29eb97b: Add a Faction model class&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/29eb97b0f341a5bdfa12d6a21511be9e48821801/src/features/unitInfo/Faction.js&#34;&gt;features/unitInfo/Faction.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {Model, attr} from &amp;quot;redux-orm&amp;quot;;

export default class Faction extends Model {
    static modelName = &amp;quot;Faction&amp;quot;;

    static fields = {
        id : attr(),
        name : attr(),
    };

    static parse(factionData) {
        return this.upsert(factionData);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/da9dcbf1b6de59468c42b417ee5a0ea8e64be3dc&#34;&gt;Commit da9dcbf: Add factions to sample data and parse them&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/da9dcbf1b6de59468c42b417ee5a0ea8e64be3dc/src/data/sampleData.js&#34;&gt;data/sampleData.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;    designs : [
        // ommitted
    ],
+   factions : [
+       {id : &amp;quot;cc&amp;quot;, name : &amp;quot;Capellan Confederation&amp;quot;},
+       {id : &amp;quot;dc&amp;quot;, name : &amp;quot;Draconis Combine&amp;quot;},
+       {id : &amp;quot;elh&amp;quot;, name : &amp;quot;Eridani Light Horse&amp;quot;},
+       {id : &amp;quot;fs&amp;quot;, name : &amp;quot;Federated Suns&amp;quot;},
+       {id : &amp;quot;fwl&amp;quot;, name : &amp;quot;Free Worlds League&amp;quot;},
+       {id : &amp;quot;hr&amp;quot;, name : &amp;quot;Hansen&#39;s Roughriders&amp;quot;},
+       {id : &amp;quot;lc&amp;quot;, name : &amp;quot;Lyran Commonwealth&amp;quot;},
+       {id : &amp;quot;wd&amp;quot;, name : &amp;quot;Wolf&#39;s Dragoons&amp;quot;},
+   ]
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/da9dcbf1b6de59468c42b417ee5a0ea8e64be3dc/src/app/reducers/entitiesReducer.js&#34;&gt;app/reducers/entitiesReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;export function loadData(state, payload) {
    // Create a Redux-ORM session from our entities &amp;quot;tables&amp;quot;
    const session = orm.session(state);
    // Get a reference to the correct version of model classes for this Session
-   const {Unit, Pilot, Mech, MechDesign} = session;
+   const {Unit, Faction, Pilot, Mech, MechDesign} = session;

-   const {unit, designs} = payload;
+   const {unit, factions, designs} = payload;

    // Clear out any existing models from state so that we can avoid
    // conflicts from the new data coming in if data is reloaded
-   [Unit, Faction, Pilot, Mech, MechDesign].forEach(modelType =&amp;gt; {
+   [Unit, Faction, Pilot, Mech, MechDesign].forEach(modelType =&amp;gt; {
        modelType.all().toModelArray().forEach(model =&amp;gt; model.delete());
    });

    // Immutably update the session state as we insert items
    Unit.parse(unit);

+    factions.forEach(faction =&amp;gt; Faction.parse(faction));
    designs.forEach(design =&amp;gt; MechDesign.parse(design));

    // Return the new &amp;quot;tables&amp;quot; object containing the updates
    return session.state;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next, now that factions are also a model type, our &lt;code&gt;Unit.affiliation&lt;/code&gt; field needs to change from a simple attribute to a foreign key reference to the &lt;code&gt;Faction&lt;/code&gt; table.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/740e602e93a8f2454323b6429756bed4579f89dc&#34;&gt;Commit 740e602: Update Unit affiliation to point to Factions&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/740e602e93a8f2454323b6429756bed4579f89dc/src/features/unitInfo/Unit.js&#34;&gt;features/unitInfo/Unit.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;-import {Model, many, attr} from &amp;quot;redux-orm&amp;quot;;
+import {Model, many, fk, attr} from &amp;quot;redux-orm&amp;quot;;


export default class Unit extends Model {
    static modelName = &amp;quot;Unit&amp;quot;;

    static fields = {
        id : attr(),
        name : attr(),
-       affiliation : attr(),
+       affiliation : fk(&amp;quot;Faction&amp;quot;),
        color : attr(),
        pilots : many(&amp;quot;Pilot&amp;quot;),
        mechs : many(&amp;quot;Mech&amp;quot;)
    };
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we can update the &lt;code&gt;&amp;lt;UnitInfoForm&amp;gt;&lt;/code&gt; component to read the list of factions from Redux and display them.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/50aaf10fa2a4abc50c952ea071d04693889815fa&#34;&gt;Commit 50aaf10: Use faction entries to populate affiliation dropdown&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/50aaf10fa2a4abc50c952ea071d04693889815fa/src/features/unitInfo/UnitInfo/UnitInfoForm.jsx&#34;&gt;features/unitInfo/UnitInfo/UnitInfoForm.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;-const FACTIONS = [
-   {value : &amp;quot;cc&amp;quot;, text : &amp;quot;Capellan Confederation&amp;quot;},
-   {value : &amp;quot;dc&amp;quot;, text : &amp;quot;Draconis Combine&amp;quot;},
-   {value : &amp;quot;elh&amp;quot;, text : &amp;quot;Eridani Light Horse&amp;quot;},
-   {value : &amp;quot;fs&amp;quot;, text : &amp;quot;Federated Suns&amp;quot;},
-   {value : &amp;quot;fwl&amp;quot;, text : &amp;quot;Free Worlds League&amp;quot;},
-   {value : &amp;quot;hr&amp;quot;, text : &amp;quot;Hansen&#39;s Roughriders&amp;quot;},
-   {value : &amp;quot;lc&amp;quot;, text : &amp;quot;Lyran Commonwealth&amp;quot;},
-   {value : &amp;quot;wd&amp;quot;, text : &amp;quot;Wolf&#39;s Dragoons&amp;quot;},
-];

-const mapState = (state) =&amp;gt; ({
-    unitInfo : selectUnitInfo(state),
-});

+import {getEntitiesSession} from &amp;quot;features/entities/entitySelectors&amp;quot;;

+const mapState = (state) =&amp;gt; {
+    const session = getEntitiesSession(state);
+    const {Faction} = session;
+
+    const factions = Faction.all().toRefArray();
+
+    const unitInfo = selectUnitInfo(state);
+
+    return {factions,unitInfo};
+};

class UnitInfoForm extends Component {
    render() {
-       const {unitInfo, updateUnitInfo} = this.props;
+       const {unitInfo, updateUnitInfo, factions} = this.props;
        const {name, affiliation, color} = unitInfo;

+       const displayFactions = factions.map(faction =&amp;gt; {
+           return {
+               value : faction.id,
+               text : faction.name
+           };
+       });
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;connecting-the-unit-model&#34;&gt;Connecting the Unit Model&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;&amp;lt;UnitInfoForm&amp;gt;&lt;/code&gt; is now in an awkward situation.  It&#39;s still showing data from &lt;code&gt;state.unitInfo&lt;/code&gt;, and &lt;code&gt;state.unitInfo&lt;/code&gt; in turn contains the entire &lt;code&gt;unit&lt;/code&gt; section from the sample data.  If you inspect the current state tree, you&#39;d see that we actually have all of the data arrays nested in there, like &lt;code&gt;state.unitInfo.pilots&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In addition, the inputs are also hooked up to apply updates to the &lt;code&gt;state.unitInfo&lt;/code&gt; section.  We really need to change that so that the form displays the values from the &lt;code&gt;Unit&lt;/code&gt; model we&#39;ve loaded in via Redux-ORM, and the updates are applied there as well.&lt;/p&gt;

&lt;p&gt;For now, we&#39;ll assume that we only have a single &lt;code&gt;Unit&lt;/code&gt; model in memory.  (Hopefully someday we&#39;ll get far enough that we can load multiple units at once, in which case that assumption will change, but it&#39;ll work for now.)&lt;/p&gt;

&lt;p&gt;We&#39;ll start by changing the form to read the current &lt;code&gt;Unit&lt;/code&gt; entry and display its values instead of from &lt;code&gt;state.unitInfo&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/b08a2482bb2b6b990582d2bd939a901c88b185f6&#34;&gt;Commit b08a248: Update unit info form to display current Unit details&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/b08a2482bb2b6b990582d2bd939a901c88b185f6/src/features/unitInfo/unitInfoSelectors.js&#34;&gt;features/unitInfo/unitInfoSelectors.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {createSelector} from &amp;quot;reselect&amp;quot;;
import {getEntitiesSession} from &amp;quot;features/entities/entitySelectors&amp;quot;;

export const selectUnitInfo = state =&amp;gt; state.unitInfo;

export const selectCurrentUnitInfo = createSelector(
    getEntitiesSession,
    (session) =&amp;gt; {
        const {Unit} = session;
        const currentUnitModel = Unit.all().first();

        let currentUnitInfo = null;

        if(currentUnitModel) {
            currentUnitInfo = currentUnitModel.ref;
        }

        return currentUnitInfo;
    }
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We&#39;ll add a selector that knows how to read the plain JS object for the current &lt;code&gt;Unit&lt;/code&gt;.  Since we assume that there&#39;s only one unit at a time, &lt;code&gt;Unit.all().first()&lt;/code&gt; should return us the model instance for that one unit, or &lt;code&gt;undefined&lt;/code&gt; if it doesn&#39;t exist.  Assuming the unit instance does exist, we can grab the underlying plain JS object reference from the model instance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/b08a2482bb2b6b990582d2bd939a901c88b185f6/src/features/unitInfo/UnitInfo/UnitInfoForm.jsx&#34;&gt;features/unitInfo/UnitInfo/UnitInfoForm.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {getEntitiesSession} from &amp;quot;features/entities/entitySelectors&amp;quot;;

-import {selectUnitInfo} from &amp;quot;../unitInfoSelectors&amp;quot;;
+import {selectCurrentUnitInfo} from &amp;quot;../unitInfoSelectors&amp;quot;;
import {updateUnitInfo, setUnitColor} from &amp;quot;../unitInfoActions&amp;quot;;


const mapState = (state) =&amp;gt; {
    const session = getEntitiesSession(state);
    const {Faction} = session;

    const factions = Faction.all().toRefArray();
    
-   const unitInfo = selectUnitInfo(state);
+   const unitInfo = selectCurrentUnitInfo(state);

    return { factions, unitInfo };
};

class UnitInfoForm extends Component {
    render() {
        const {unitInfo, factions} = this.props;
+       const isDisplayingUnit = Boolean(unitInfo);
+       let name = &amp;quot;&amp;quot;, affiliation = null, color = null;
+
+       if(isDisplayingUnit) {
+           ({name, affiliation, color} = unitInfo);
+       }

        // omit other rendering code
                        &amp;lt;input
                            placeholder=&amp;quot;Name&amp;quot;
                            name=&amp;quot;name&amp;quot;
+                           disabled={!isDisplayingUnit}
                        /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Within the &lt;code&gt;&amp;lt;UnitInfoForm&amp;gt;&lt;/code&gt;, we switch up which selector we&#39;re using to retrieve the unit info values.  &lt;strong&gt;Note that we &lt;em&gt;could&lt;/em&gt; have used the same selector name and switched the way it was retrieving data, instead&lt;/strong&gt;.  This is an example of keeping the changing data storage abstracted from the component itself.&lt;/p&gt;

&lt;p&gt;Inside the component, we&#39;re adding some additional logic to properly disable the input fields if there&#39;s no unit loaded into memory.  If you look inside the &lt;code&gt;if&lt;/code&gt; clause, there&#39;s a neat little trick you can use to do destructuring assignment to variables that have already been declared using &lt;code&gt;let&lt;/code&gt; or &lt;code&gt;var&lt;/code&gt; - put parentheses around the entire statement.  We could also have possibly handled the &lt;code&gt;isDisplayingUnit&lt;/code&gt; check by doing &lt;code&gt;const {unitInfo = {}} = this.props&lt;/code&gt;, and checking to see if it actually had any fields inside.&lt;/p&gt;

&lt;p&gt;Now things get a bit interesting.  Currently, our &lt;code&gt;unitInfoReducer&lt;/code&gt; is a slice reducer that handles updates to &lt;code&gt;state.unitInfo&lt;/code&gt;.  What we need instead is a feature reducer that handles updates to the &lt;code&gt;Unit&lt;/code&gt; entry that&#39;s stored in &lt;code&gt;state.entities.Unit&lt;/code&gt;.  Fortunately, the rewrite isn&#39;t overly complicated, thanks to the other reducer utility functions we already have available.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/2a6592be28075980c9c92524cb1bee577e893267&#34;&gt;Commit 2a6592b: Rewrite unit info reducer to update current Unit model&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/2a6592be28075980c9c92524cb1bee577e893267/src/features/unitInfo/unitInfoReducer.js&#34;&gt;features/unitInfo/unitInfoReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;-import {createConditionalSliceReducer} from &amp;quot;common/utils/reducerUtils&amp;quot;;
-import {DATA_LOADED} from &amp;quot;features/tools/toolConstants&amp;quot;;
+import orm from &amp;quot;app/schema&amp;quot;;
+import {createConditionalSliceReducer} from &amp;quot;common/utils/reducerUtils&amp;quot;;

import {
    UNIT_INFO_UPDATE,
    UNIT_INFO_SET_COLOR,
} from &amp;quot;./unitInfoConstants&amp;quot;;

-const initialState = {
-   name : &amp;quot;N/A&amp;quot;,
-   affiliation : &amp;quot;&amp;quot;,
-   color : &amp;quot;blue&amp;quot;
-};

-function dataLoaded(state, payload) {
-   const {unit} = payload;
-   return unit;
-}

function updateUnitInfo(state, payload) {
-   return {
-       ...state,
-       ...payload,
-   };
+   const session = orm.session(state);
+   const {Unit} = session;
+
+   const currentUnit = Unit.all().first();
+
+   if(currentUnit) {
+       currentUnit.update(payload);
+   }
+
+   return session.state;
}

function setUnitColor(state, payload) {
    const {color} = payload;
    
-   return {
-       ...state,
-       color
-   };
+   const session = orm.session(state);
+   const {Unit} = session;
+
+   const currentUnit = Unit.all().first();
+
+   if(currentUnit) {
+       currentUnit.color = color;
+   }

+   return session.state;
}

-export default createReducer(initialState, {
-   [DATA_LOADED] : dataLoaded,
+export default createConditionalSliceReducer(&amp;quot;entities&amp;quot;, {
    [UNIT_INFO_UPDATE] : updateUnitInfo,
    [UNIT_INFO_SET_COLOR] : setUnitColor,
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The diff might be a bit difficult to read, so here&#39;s what we did:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We removed the &lt;code&gt;DATA_LOADED&lt;/code&gt; constant and case reducer that just copied over the &lt;code&gt;unit&lt;/code&gt; section from the sample data&lt;/li&gt;
&lt;li&gt;Both &lt;code&gt;updateUnitInfo()&lt;/code&gt; and &lt;code&gt;setUnitColor()&lt;/code&gt; case reducers now expect that &lt;code&gt;state&lt;/code&gt; is actually the entire &lt;code&gt;state.entities&lt;/code&gt; slice.  They create a &lt;code&gt;Session&lt;/code&gt; instance, look up the &lt;code&gt;Unit&lt;/code&gt; model, and update the appropriate fields before returning the updated &lt;code&gt;state.entities&lt;/code&gt; data.&lt;/li&gt;
&lt;li&gt;The exported reducer now uses &lt;code&gt;createConditionalSliceReducer()&lt;/code&gt; so that our case reducers only see the &lt;code&gt;state.entities&lt;/code&gt; slice, and only if it&#39;s one of the action types this reducer knows how to handle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/2a6592be28075980c9c92524cb1bee577e893267/src/app/reducers/rootReducer.js&#34;&gt;app/reducers/rootReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;const combinedReducer = combineReducers({
    entities : entitiesReducer,
    editingEntities : editingEntitiesReducer,
-   unitInfo : unitInfoReducer,
    pilots : pilotsReducer,
    mechs : mechsReducer,
    tabs : tabReducer,
    modals : modalsReducer,
    contextMenu : contextMenuReducer
});

const rootReducer = reduceReducers(
    combinedReducer,
    entityCrudReducer,
    editingFeatureReducer,
+   unitInfoReducer,
);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With the &lt;code&gt;unitInfoReducer&lt;/code&gt; rewritten, we just need to update our root reducer so that we now longer have a &lt;code&gt;state.unitInfo&lt;/code&gt; slice, and instead have the &lt;code&gt;unitInfoReducer&lt;/code&gt; added to the sequential top-level &amp;quot;feature reducers&amp;quot; list.&lt;/p&gt;

&lt;p&gt;At this point you might be thinking: &amp;quot;Hey, don&#39;t we already have a bunch of logic for updating models in the store?&amp;quot;  Indeed, we do.  However, as mentioned earlier, those assume that the model has been copied to &lt;code&gt;state.editingEntities&lt;/code&gt; first.  We&#39;ll probably tackle that in the not-too-distant future, but for now it&#39;s simpler to let this be a special case where the edits are applied directly to the data that&#39;s in &lt;code&gt;state.entities&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&#34;displaying-unit-data-as-a-tree&#34;&gt;Displaying Unit Data as a Tree&lt;/h2&gt;

&lt;p&gt;We&#39;re now ready to do something interesting and useful with the &amp;quot;Unit Table of Organization&amp;quot; tree.  We&#39;re going to connect the tree so that it displays the lances in the unit and the pilots in each lance, based on the actual data in the Redux store, and we&#39;re going to load that data as a nested structure from our sample data.&lt;/p&gt;

&lt;h3 id=&#34;loading-lance-data&#34;&gt;Loading Lance Data&lt;/h3&gt;

&lt;p&gt;Again, our first step is to add a &lt;code&gt;Lance&lt;/code&gt; model.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/5485b10599c3655d6d521af6b0022d87a448dcc1&#34;&gt;Commit 5485b10: Add Lance model&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/5485b10599c3655d6d521af6b0022d87a448dcc1/src/features/unitInfo/Lance.js&#34;&gt;features/unitInfo/Lance.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {Model, many, attr} from &amp;quot;redux-orm&amp;quot;;

export default class Lance extends Model {
    static modelName = &amp;quot;Lance&amp;quot;;

    static fields = {
        id : attr(),
        name : attr(),
        pilots : many(&amp;quot;Pilot&amp;quot;)
    };

    static parse(lanceData) {
        return this.upsert(lanceData);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then we&#39;ll update the sample data to include info on the lance names and which pilots they contain, and parse that in as part of &lt;code&gt;Unit&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/14cd310d006bd16467f2ff2a30128696cb0a28ee&#34;&gt;Commit 14cd310: Add lance data and parse lances when loading a Unit&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/14cd310d006bd16467f2ff2a30128696cb0a28ee/src/data/sampleData.js&#34;&gt;data/sampleData.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;const sampleData = {
    unit : {
        id : 1,
        name : &amp;quot;Black Widow Company&amp;quot;,
        affiliation : &amp;quot;wd&amp;quot;,
        color : &amp;quot;black&amp;quot;,
-       lances : [],
+       lances : [
+           {
+               id : 1,
+               name : &amp;quot;Command Lance&amp;quot;,
+               pilots : [
+                   1, 2, 3, 4
+               ]
+           },
+           {
+               id : 2,
+               name : &amp;quot;Fire Lance&amp;quot;,
+               pilots : [
+                   5, 6, 7, 8
+               ]
+           },
+           {
+               id : 3,
+               name : &amp;quot;Recon Lance&amp;quot;,
+               pilots : [
+                   9, 10, 11, 12
+               ]
+           }
+       ],
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/14cd310d006bd16467f2ff2a30128696cb0a28ee/src/features/unitInfo/Unit.js&#34;&gt;features/unitInfo/Unit.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;export default class Unit extends Model {
    static modelName = &amp;quot;Unit&amp;quot;;

    static fields = {
        id : attr(),
        name : attr(),
        affiliation : fk(&amp;quot;Faction&amp;quot;),
        color : attr(),
+       lances : many(&amp;quot;Lance&amp;quot;),
        pilots : many(&amp;quot;Pilot&amp;quot;),
        mechs : many(&amp;quot;Mech&amp;quot;)
    };

    static parse(unitData) {
-       const {Pilot, Mech} = this.session;
+       const {Pilot, Mech, Lance} = this.session;

        const parsedData = {
            ...unitData,
+           lances : unitData.lances.map(lanceEntry =&amp;gt; Lance.parse(lanceEntry)),
            pilots : unitData.pilots.map(pilotEntry =&amp;gt; Pilot.parse(pilotEntry)),
            mechs : unitData.mechs.map(mechEntry =&amp;gt; Mech.parse(mechEntry)),
        };

        return this.upsert(parsedData);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;connecting-the-unit-organization-tree&#34;&gt;Connecting the Unit Organization Tree&lt;/h3&gt;

&lt;p&gt;We already moved &lt;code&gt;UnitOrganization.jsx&lt;/code&gt; from &lt;code&gt;features/unitOrganization&lt;/code&gt; to &lt;code&gt;features/unitInfo&lt;/code&gt;.  Now we&#39;ll move it into its own folder, because we&#39;re going to start extracting more components out of its current contents.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/54fa32fbccb74dcea94c7cef4c767090753084c1&#34;&gt;Commit 54fa32fb: Move UnitOrganizationTree into its own folder&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Looking at the contents of the &lt;code&gt;&amp;lt;UnitOrganizationTree&amp;gt;&lt;/code&gt; component, we can see a lot of repetition in the structure.  A good place to start would be extracting a separate component that displays a single pilot entry.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/7385be9c019e7f39111c5b54f1dd0100282e03eb&#34;&gt;Commit 7385be9: Add a LancePilot component&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/7385be9c019e7f39111c5b54f1dd0100282e03eb/src/features/unitInfo/UnitOrganizationTree/LancePilot.jsx&#34;&gt;features/unitInfo/UnitOrganizationTree/LancePilot.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import React from &amp;quot;react&amp;quot;;
import {connect} from &amp;quot;react-redux&amp;quot;;

import {
    List,
} from &amp;quot;semantic-ui-react&amp;quot;;

import {getEntitiesSession} from &amp;quot;features/entities/entitySelectors&amp;quot;;

const mapState = (state, ownProps) =&amp;gt; {
    const session = getEntitiesSession(state);
    const {Pilot} = session;

    let pilot, mech;

    if(Pilot.hasId(ownProps.pilotID)) {
        const pilotModel = Pilot.withId(ownProps.pilotID);

        pilot = pilotModel.ref;

        if(pilotModel.mech) {
            mech = pilotModel.mech.type.ref;
        }
    }

    return {pilot, mech};
};

const UNKNOWN_PILOT =  {name : &amp;quot;Unknown&amp;quot;, rank : &amp;quot;&amp;quot;}
const UNKNOWN_MECH = {id : &amp;quot;N/A&amp;quot;, name : &amp;quot;&amp;quot;};

const LancePilot = ({pilot = UNKNOWN_PILOT, mech = UNKNOWN_MECH}) =&amp;gt; {
    const {name, rank} = pilot;
    const {id : mechModel, name : mechName} = mech;

    return (
        &amp;lt;List.Item&amp;gt;
            &amp;lt;List.Icon name=&amp;quot;user&amp;quot; /&amp;gt;
            &amp;lt;List.Content&amp;gt;
                &amp;lt;List.Header&amp;gt;{rank} {name} - {mechModel} {mechName}&amp;lt;/List.Header&amp;gt;
            &amp;lt;/List.Content&amp;gt;
        &amp;lt;/List.Item&amp;gt;
    )
};

export default connect(mapState)(LancePilot);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We connect this component in the same way that we connected the &lt;code&gt;&amp;lt;PilotsListRow&amp;gt;&lt;/code&gt; component previously.  The connected component will receive a &lt;code&gt;pilotID&lt;/code&gt; prop, and use that to look up the appropriate &lt;code&gt;Pilot&lt;/code&gt; model from the store.  Assuming that a pilot by that ID exists, it will also look up the related &lt;code&gt;Mech&lt;/code&gt; entry so that we can display both the name of the pilot and the type of mech assigned to that pilot.&lt;/p&gt;

&lt;p&gt;Since we have a fixed list of pilot entries right now, we can rewrite &lt;code&gt;&amp;lt;UnitOrganizationTree&amp;gt;&lt;/code&gt; to render individual &lt;code&gt;&amp;lt;LancePilot&amp;gt;&lt;/code&gt; components with fixed pilot IDs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/01e506b890cefe1a50678d9403597381694dcfeb&#34;&gt;Commit 01e506b: Show hardcoded lance members by ID in the Unit TOE tree&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/01e506b890cefe1a50678d9403597381694dcfeb/src/features/unitInfo/UnitOrganizationTree/UnitOrganizationTree.jsx&#34;&gt;features/unitInfo/UnitOrganizationTree/UnitOrganizationTree.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;       &amp;lt;List.Content&amp;gt;
            &amp;lt;List.Header&amp;gt;Command Lance&amp;lt;/List.Header&amp;gt;
            &amp;lt;List.List&amp;gt;
-               &amp;lt;List.Item&amp;gt;
-                   &amp;lt;List.Icon name=&amp;quot;user&amp;quot; /&amp;gt;
-                   &amp;lt;List.Content&amp;gt;
-                       &amp;lt;List.Header&amp;gt;Cpt. Natasha Kerensky - WHM-6R Warhammer&amp;lt;/List.Header&amp;gt;
-                   &amp;lt;/List.Content&amp;gt;
-               &amp;lt;/List.Item&amp;gt;
+               &amp;lt;LancePilot pilotID={1} /&amp;gt;
                // etc
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we refresh the page, we&#39;ll see 12 rows of &lt;code&gt;Unknown - N/A&lt;/code&gt; lines inside of the tree until we load the pilot data.  That&#39;s sort of good, because we know that the connected components are rendering and safely handling the case where the data doesn&#39;t exist.&lt;/p&gt;

&lt;p&gt;The next step is to do the same thing for the lance entries.  We&#39;ll extract the UI layout into a &lt;code&gt;&amp;lt;Lance&amp;gt;&lt;/code&gt; component, and have that component render a list of &lt;code&gt;&amp;lt;LancePilot&amp;gt;&lt;/code&gt; components based on the associated pilot IDs for that &lt;code&gt;Lance&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/b2cba10ea94a6bea5e29b94d38bcb67ad261cf58&#34;&gt;Commit b2cba10: Add a Lance component&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/b2cba10ea94a6bea5e29b94d38bcb67ad261cf58/src/features/unitInfo/UnitOrganizationTree/Lance.jsx&#34;&gt;features/unitInfo/UnitOrganizationTree/Lance.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import React from &amp;quot;react&amp;quot;;
import {connect} from &amp;quot;react-redux&amp;quot;;

import {
    List,
} from &amp;quot;semantic-ui-react&amp;quot;;

import {getEntitiesSession} from &amp;quot;features/entities/entitySelectors&amp;quot;;

import LancePilot from &amp;quot;./LancePilot&amp;quot;;

const mapState = (state, ownProps) =&amp;gt; {
    const session = getEntitiesSession(state);
    const {Lance} = session;

    let lance, pilots;

    if(Lance.hasId(ownProps.lanceID)) {
        const lanceModel = Lance.withId(ownProps.lanceID);

        lance = lanceModel.ref;
        pilots = lanceModel.pilots.toRefArray().map(pilot =&amp;gt; pilot.id);
    }

    return {lance, pilots};
};

const UNKNOWN_LANCE =  {name : &amp;quot;Unknown&amp;quot;}

const Lance = ({lance = UNKNOWN_LANCE, pilots = []}) =&amp;gt; {
    const {name} = lance;

    const lancePilots = pilots.map(pilotID =&amp;gt; &amp;lt;LancePilot key={pilotID} pilotID={pilotID} /&amp;gt;);

    return (
        &amp;lt;List.Item&amp;gt;
            &amp;lt;List.Icon name=&amp;quot;cube&amp;quot; /&amp;gt;
            &amp;lt;List.Content&amp;gt;
                &amp;lt;List.Header&amp;gt;{name}&amp;lt;/List.Header&amp;gt;
                &amp;lt;List.List&amp;gt;
                    {lancePilots}
                &amp;lt;/List.List&amp;gt;
            &amp;lt;/List.Content&amp;gt;
        &amp;lt;/List.Item&amp;gt;
    )
};

export default connect(mapState)(Lance);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Pretty similar to the &lt;code&gt;&amp;lt;LancePilot&amp;gt;&lt;/code&gt; component, except that we now look up the list of pilots associated to the lance and extract an array of their IDs as a separate prop.&lt;/p&gt;

&lt;p&gt;With that component created, we can simplify &lt;code&gt;&amp;lt;UnitOrganizationTree&amp;gt;&lt;/code&gt; further.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/d1d5a75a2381bd085f3ce3bb9309136e5160e044&#34;&gt;Commit d1d5a75: Show hardcoded lances by ID in the Unit TOE tree&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/d1d5a75a2381bd085f3ce3bb9309136e5160e044/src/features/unitInfo/UnitOrganizationTree/UnitOrganizationTree.jsx&#34;&gt;features/unitInfo/UnitOrganizationTree/UnitOrganizationTree.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;    &amp;lt;List.Content&amp;gt;
        &amp;lt;List.Header&amp;gt;Black Widow Company&amp;lt;/List.Header&amp;gt;
        &amp;lt;List.List&amp;gt;
-           &amp;lt;List.Item&amp;gt;
-               &amp;lt;List.Icon name=&amp;quot;cube&amp;quot; /&amp;gt;
-               &amp;lt;List.Content&amp;gt;
-                   &amp;lt;List.Header&amp;gt;Command Lance&amp;lt;/List.Header&amp;gt;
-                   &amp;lt;List.List&amp;gt;
-                       &amp;lt;LancePilot pilotID={1} /&amp;gt;
-                       &amp;lt;LancePilot pilotID={2} /&amp;gt;
-                       &amp;lt;LancePilot pilotID={3} /&amp;gt;
-                       &amp;lt;LancePilot pilotID={4} /&amp;gt;
-                   &amp;lt;/List.List&amp;gt;
-               &amp;lt;/List.Content&amp;gt;
-           &amp;lt;/List.Item&amp;gt;
+           &amp;lt;Lance lanceID={1} /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Again, a refresh of the page will show three &amp;quot;Unknown&amp;quot; entries in the tree, with no pilot children this time.  Once we load the sample data, the entire tree should populate.&lt;/p&gt;

&lt;p&gt;We&#39;re still showing a hardcoded list of lances, and that should really be driven based on the lances that are actually in the store.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/eca88380cf56844e54d0f3804b83f7342a024093&#34;&gt;Commit eca8838: Show lances in the Unit TOE tree based on current Unit entry contents&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/eca88380cf56844e54d0f3804b83f7342a024093/src/features/unitInfo/UnitOrganizationTree/UnitOrganizationTree.jsx&#34;&gt;features/unitInfo/UnitOrganization/UnitOrganizationTree.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import React from &amp;quot;react&amp;quot;;
+import {connect} from &amp;quot;react-redux&amp;quot;;

import {
    List,
} from &amp;quot;semantic-ui-react&amp;quot;;

+import {getEntitiesSession} from &amp;quot;features/entities/entitySelectors&amp;quot;;

import Lance from &amp;quot;./Lance&amp;quot;;

+const mapState = (state) =&amp;gt; {
+   const session = getEntitiesSession(state);
+   const {Unit} = session;
+
+   let lances;
+
+   const unitModel = Unit.all().first();
+
+   if(unitModel) {
+       lances = unitModel.lances.toRefArray().map(lance =&amp;gt; lance.id);
+   }
+
+   return {lances};
+}

-const UnitOrganizationTree = () =&amp;gt; {
+const UnitOrganizationTree = ({lances = []}) =&amp;gt; {
+    const lanceEntries = lances.map(lanceID =&amp;gt; &amp;lt;Lance key={lanceID} lanceID={lanceID} /&amp;gt;);

    return (
        &amp;lt;List size=&amp;quot;large&amp;quot;&amp;gt;
            &amp;lt;List.Item&amp;gt;
                &amp;lt;List.Icon name=&amp;quot;cubes&amp;quot; /&amp;gt;
                &amp;lt;List.Content&amp;gt;
                    &amp;lt;List.Header&amp;gt;Black Widow Company&amp;lt;/List.Header&amp;gt;
                    &amp;lt;List.List&amp;gt;
-                       &amp;lt;Lance lanceID={1} /&amp;gt;
-                       &amp;lt;Lance lanceID={2} /&amp;gt;
-                       &amp;lt;Lance lanceID={3} /&amp;gt;
+                       {lanceEntries}
                    &amp;lt;/List.List&amp;gt;
                &amp;lt;/List.Content&amp;gt;
            &amp;lt;/List.Item&amp;gt;
        &amp;lt;/List&amp;gt;
    )
}

export default connect(mapState)(UnitOrganizationTree);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now when we refresh the page, the tree is empty except for the parent tree list item with the title &amp;quot;Black Widow Company&amp;quot;.  Loading the sample data will fill out the entire tree.&lt;/p&gt;

&lt;p&gt;There&#39;s one final update to make here.  Let&#39;s have that parent tree node render the current name of the unit, and show the affiliation color and values as well, so that we can see them update as we edit them in the &lt;code&gt;&amp;lt;UnitInfoForm&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/cf8e19c699fa80f3f9c7fca57e812f6bb165f240&#34;&gt;Commit cf8e19c: Show current unit detail values in the Unit TOE tree&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/cf8e19c699fa80f3f9c7fca57e812f6bb165f240/src/features/unitInfo/UnitOrganizationTree/UnitOrganizationTree.jsx&#34;&gt;features/unitInfo/UnitOrganizationTree/UnitOrganizationTree.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;const mapState = (state) =&amp;gt; {
    const session = getEntitiesSession(state);
    const {Unit} = session;

-   let lances;
+   let unit, faction, lances;

    const unitModel = Unit.all().first();

    if(unitModel) {
+        unit = unitModel.ref;
+        faction = unitModel.affiliation.ref;
        lances = unitModel.lances.toRefArray().map(lance =&amp;gt; lance.id);
    }

-   return {lances};
+   return {unit, faction, lances};
}

+const UNKNOWN_UNIT = {name : &amp;quot;Unknown&amp;quot;};

-const UnitOrganizationTree = ({lances = []}) =&amp;gt; {
+const UnitOrganizationTree = ({unit = UNKNOWN_UNIT, faction = {}, lances = []}) =&amp;gt; {
+   const {name, color} = unit;
+   const {name : factionName} = faction;

+   const colorBlock = &amp;lt;div
+       style={{
+           marginLeft : 10,
+           backgroundColor : color,
+           border : &amp;quot;1px solid black&amp;quot;,
+           height : 20,
+           width : 40,
+       }}
+   /&amp;gt;;

+   const displayText = factionName ? `${name} / ${factionName}` : name;

    const lanceEntries = lances.map(lanceID =&amp;gt; &amp;lt;Lance key={lanceID} lanceID={lanceID} /&amp;gt;);

    return (
        &amp;lt;List size=&amp;quot;large&amp;quot;&amp;gt;
            &amp;lt;List.Item&amp;gt;
                &amp;lt;List.Icon name=&amp;quot;cubes&amp;quot; /&amp;gt;
                &amp;lt;List.Content&amp;gt;
-                   &amp;lt;List.Header&amp;gt;Black Widow Company&amp;lt;/List.Header&amp;gt;
+                   &amp;lt;List.Header style={{display : &amp;quot;flex&amp;quot;}}&amp;gt;{displayText} {colorBlock}&amp;lt;/List.Header&amp;gt;
                    &amp;lt;List.List&amp;gt;
                        {lanceEntries}
                    &amp;lt;/List.List&amp;gt;
                &amp;lt;/List.Content&amp;gt;
            &amp;lt;/List.Item&amp;gt;
        &amp;lt;/List&amp;gt;
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Notice that our tree component structure works the same way as our connected list: connected parent components using lists of IDs to render child components, and connected child components reading their own data from the store using the ID.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This tree is relatively simple, and has a fixed size, but the general pattern could be applied to a truly recursive tree as well.  In fact, there&#39;s already a &lt;a href=&#34;https://github.com/reactjs/redux/tree/3e74e002a39217dd40e9b4362eca903779b227f0/examples/tree-view&#34;&gt;treeview example in the Redux repo&lt;/a&gt;.  For background, see &lt;a href=&#34;https://github.com/reactjs/redux/pull/1269&#34;&gt;the PR from Dan Abramov adding the treeview example&lt;/a&gt;.  (It&#39;s also interesting to read the discussion on that PR, as that&#39;s where the official guidance and collective wisdom really transitioned from &amp;quot;connect one component at the top of the component tree&amp;quot; to &amp;quot;connect many components deeper for better performance&amp;quot;.)&lt;/p&gt;

&lt;p&gt;Let&#39;s take a final look at the updated Unit Organization Tree:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2018-01-practical-redux-part-11/unit-organization-tree.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2018-01-practical-redux-part-11/unit-organization-tree.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;h2 id=&#34;final-thoughts&#34;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;I&#39;m really excited to be continuing with this series.  We&#39;re slowly starting to increase the level of complexity and difficulty in these examples, and I&#39;ve got plenty more topics I want to cover.  In the next couple parts, I hope to show how to edit complex nested/relational data, and then finally cover asynchronous logic and side effects.&lt;/p&gt;

&lt;p&gt;As always, comments, feedback, and suggestions are greatly appreciated!&lt;/p&gt;

&lt;h2 id=&#34;further-information&#34;&gt;Further Information&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Upgrading to React 16&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://reactjs.org/blog/2017/09/26/react-v16.0.html&#34;&gt;React blog: 16.0 announcement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://reactjs.org/blog/2017/11/28/react-v16.2.0-fragment-support.html&#34;&gt;React blog: 16.2 announcement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.discordapp.com/lessons-from-migrating-a-large-codebase-to-react-16-e60e49102aa6&#34;&gt;Discord blog: Lessons from migrating a large codebase to React 16&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://jamesknelson.com/experience-react-16/&#34;&gt;James K Nelson: My experience with React 16&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.benmvp.com/slides/2017/reactboston/fiber.html#/&#34;&gt;Ben Ilegbodu: React Fiber for the rest of us&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.robinwieruch.de/what-is-new-in-react-16/&#34;&gt;Robin Wieruch: What&#39;s new in React 16?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Random Numbers in Redux&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://daveceddia.com/random-numbers-in-redux/&#34;&gt;Roll the Dice: Random Numbers in Redux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.ohlman.io/random-in-redux-b6b9932ad061&#34;&gt;Random in Redux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Project Structuring and Containers&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gist.github.com/markerikson/ea312b5ee398627ffceb09f89904831f&#34;&gt;Reactiflux chat log: thoughts on Redux container/presentational structuring&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/react-redux-links/blob/master/project-structure.md&#34;&gt;React/Redux Links: Project Structure&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Redux Treeviews&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/reactjs/redux/tree/3e74e002a39217dd40e9b4362eca903779b227f0/examples/tree-view&#34;&gt;Redux examples: Tree View&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/reactjs/redux/pull/1269&#34;&gt;Redux PR #1269: Add a tree view example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    
    <item>
      <title>Practical Redux course now available on Educative.io!</title>
      <link>https://blog.isquaredsoftware.com/2017/11/practical-redux-educative-course/</link>
      <pubDate>Tue, 28 Nov 2017 10:00:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2017/11/practical-redux-educative-course/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;p&gt;I&#39;m &lt;em&gt;very&lt;/em&gt; excited to announce that &lt;span style=&#34;font-size: larger;&#34;&gt;&lt;strong&gt;my &amp;quot;Practical Redux&amp;quot; tutorial series &lt;a href=&#34;https://www.educative.io/collection/5687753853370368/5707702298738688&#34;&gt;is now an interactive course on Educative.io&lt;/a&gt;!&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Ever since I started writing this series, I&#39;ve had people suggest that I ought to turn it into a book, course, or something along that line.  While I don&#39;t have any real interest in writing a book, Educative&#39;s platform for building interactive courses sounded like it would be a great fit for the material in Practical Redux.  In particular, the ability to create fully runnable in-course versions of an application is a great way to demonstrate what the app looks like as it&#39;s built.&lt;/p&gt;

&lt;p&gt;For the last several months, I&#39;ve been working on turning the Practical Redux blog posts into an Educative course.  While the course has the same core content as the posts, I didn&#39;t want it to just be a complete copy-paste duplicate of the posts.  I&#39;ve taken this as a chance to clean up, reorganize, and improve several sections of the content, and rebuilt the &lt;strong&gt;&lt;em&gt;Project Mini-Mek&lt;/em&gt;&lt;/strong&gt; sample application as well.&lt;/p&gt;

&lt;p&gt;Here&#39;s some of the changes in the course compared to the posts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I&#39;ve rearranged the content so that the project setup process is first.  That section now includes the info on using Yarn&#39;s &amp;quot;offline mirror&amp;quot; feature for package management.&lt;/li&gt;
&lt;li&gt;The Redux-ORM section has been heavily reworked.  It now comes in between the project setup and data loading sections, which is when you actually need to learn about it.  I&#39;ve also updated all the info on Redux-ORM to cover the v0.9 API, which simplifies several aspects of using it.&lt;/li&gt;
&lt;li&gt;I&#39;ve added an extensive summary of the info contained in the lessons, and a set of suggestions for further resources and learning.&lt;/li&gt;
&lt;li&gt;Lots of small tweaks and improvements to descriptions and wording.&lt;/li&gt;
&lt;li&gt;I rebuilt the &lt;strong&gt;&lt;em&gt;Project Mini-Mek&lt;/em&gt;&lt;/strong&gt; sample app from the first commit.  As with the written content, the code is largely the same, but I&#39;ve cleaned up some of the inconconsistencies that came from being developed over time.&lt;/li&gt;
&lt;li&gt;And, multiple runnable and editable examples of the application to show its implementation and progression throughout the course.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here&#39;s the course link:&lt;/p&gt;

&lt;p&gt;&lt;span style=&#34;font-size: 28px;&#34;&gt;&lt;a href=&#34;https://www.educative.io/collection/5687753853370368/5707702298738688&#34;&gt;Practical Redux course on Educative.io&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;You&#39;ll need a free account on Educative in order to purchase the course.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I&#39;d like to thank everyone who&#39;s read the &amp;quot;Practical Redux&amp;quot; series thus far, and especially those who have left encouraging comments or said thanks elsewhere&lt;/strong&gt;.  I&#39;ve really enjoyed writing these posts, and I&#39;ve got many more topics I want to cover in this series.  No specific timeline yet for the next post, but I&#39;m hoping to find time to resume writing the post series in the near future.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Practical Redux, Part 10: Managing Modals and Context Menus</title>
      <link>https://blog.isquaredsoftware.com/2017/07/practical-redux-part-10-managing-modals/</link>
      <pubDate>Tue, 25 Jul 2017 10:00:00 -0400</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2017/07/practical-redux-part-10-managing-modals/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/2017/07/practical-redux-part-9-managing-dependencies/&#34;&gt;Last time in Part 9&lt;/a&gt;&lt;/strong&gt;, we upgraded Redux-ORM to 0.9 and discussed the migration, updated all other app dependencies, and used Yarn&#39;s &amp;quot;offline mirror&amp;quot; feature to cache package tarballs for offline repo installation.  This time, we&#39;re going to &lt;strong&gt;set up modal dialogs that are driven by Redux, look at ways to get &amp;quot;return values&amp;quot; from dialogs while still following the principles of Redux, and implement a context menu system as well&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The code for this project is on Github at &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek&#34;&gt;github.com/markerikson/project-minimek&lt;/a&gt;&lt;/strong&gt;.  The original WIP commits I made for this post can be seen in &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/12&#34;&gt;PR #12: Practical Redux Part 10 WIP&lt;/a&gt;&lt;/strong&gt;, and the final &amp;quot;clean&amp;quot; commits can be seen in in &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/13&#34;&gt;PR #13: Practical Redux Part 10 Final&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I&#39;ll be linking to each &amp;quot;final&amp;quot; commit as I go through the post, as well as specific files in those commits.  I won&#39;t paste every changed file in here or show every single changed line, to save space, but rather try to show the most relevant changes for each commit as appropriate.&lt;/p&gt;

&lt;h3 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#adding-modal-dialogs&#34;&gt;Adding Modal Dialogs&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#driving-react-modals-from-redux&#34;&gt;Driving React Modals from Redux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#making-modals-stackable&#34;&gt;Making Modals Stackable&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#building-a-reusable-color-picker-dialog&#34;&gt;Building a Reusable Color Picker Dialog&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#creating-the-colorpickerdialog&#34;&gt;Creating the ColorPickerDialog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#using-the-dialog-result-value&#34;&gt;Using the Dialog Result Value&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#an-alternative-approach-to-dialog-results&#34;&gt;An Alternative Approach to Dialog Results&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#designing-a-context-menu-system&#34;&gt;Designing a Context Menu System&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#react-portals&#34;&gt;React Portals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#building-the-context-menu-system&#34;&gt;Building the Context Menu System&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#adding-a-context-menu-to-the-pilots-list&#34;&gt;Adding a Context Menu to the Pilots List&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#fixing-some-existing-bugs&#34;&gt;Fixing Some Existing Bugs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#final-thoughts&#34;&gt;Final Thoughts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#further-information&#34;&gt;Further Information&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;adding-modal-dialogs&#34;&gt;Adding Modal Dialogs&lt;/h2&gt;

&lt;p&gt;As I&#39;ve mentioned, this series is not really meant to result in a fully-working meaningful application.  It&#39;s primarily intended to give me reasons to show off specific useful React and Redux techniques.  That means that there&#39;s a number of things that are going to be obvious over-engineering.  Like, say, modal dialogs.  This app doesn&#39;t &lt;em&gt;need&lt;/em&gt; modal dialogs, but guess what: we&#39;re going to add modal dialogs to &lt;strong&gt;&lt;em&gt;Project Mini-Mek&lt;/em&gt;&lt;/strong&gt; anyway :)&lt;/p&gt;

&lt;p&gt;The basic concepts of handling modals in React and driving them from Redux have been described many times elsewhere, in excellent detail.  My links list has many articles on the topic, but here&#39;s a selected reading list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dave Ceddia&#39;s post on &lt;a href=&#34;https://daveceddia.com/open-modal-in-react/&#34;&gt;Modal Dialogs in React&lt;/a&gt; demonstrates the basic approach for rendering and control a modal.&lt;/li&gt;
&lt;li&gt;Dan Abramov&#39;s Stack Overflow answer on &lt;a href=&#34;https://stackoverflow.com/questions/35623656/how-can-i-display-a-modal-dialog-in-redux-that-performs-asynchronous-actions/35641680&#34;&gt;how to control modal dialogs using Redux&lt;/a&gt; shows how to write reducers that contain descriptions of a modal, and a central React component to render it.&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;David Gilbertson&#39;s post &lt;a href=&#34;https://codeburst.io/modals-in-react-f6c3ff9f4701&#34;&gt;Modals in React&lt;/a&gt;, which discusses the tradeoffs of different approaches for putting modals on top of the rest of the app&lt;/li&gt;
&lt;li&gt;Mike Vercoelen&#39;s article &lt;a href=&#34;https://codersmind.com/scalable-modals-react-redux/&#34;&gt;Scalable Modals with React and Redux&lt;/a&gt;, which shows Dan&#39;s technique for Redux-driven modals in practice&lt;/li&gt;
&lt;li&gt;And finally, my own prior blog post on &lt;a href=&#34;https://blog.isquaredsoftware.com/2016/11/posts-on-packtpub-generic-redux-modals-and-building-better-bundles/&#34;&gt;handling return values from generic &amp;quot;picker&amp;quot; modals&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We&#39;re going to put these concepts into action, and even expand on them in some ways.&lt;/p&gt;

&lt;h3 id=&#34;driving-react-modals-from-redux&#34;&gt;Driving React Modals from Redux&lt;/h3&gt;

&lt;p&gt;Let&#39;s start by putting together the pieces needed to show a single modal dialog.  We&#39;re going to need a few things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;ModalManager&lt;/code&gt; component that takes a description of what modal component to show, and what props the modal should receive, plus a lookup table of available modal components, and renders the right modal component from that description&lt;/li&gt;
&lt;li&gt;Actions and reducers that store and clear the description for the current modal&lt;/li&gt;
&lt;li&gt;An actual modal component to show&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/21777d793eacd3863a04d71480f5a30618fb7ce2&#34;&gt;Commit 21777d7: Add basic handling for a single modal dialog&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/21777d793eacd3863a04d71480f5a30618fb7ce2/src/features/modals/modalReducer.js&#34;&gt;features/modals/modalsReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {
    MODAL_CLOSE,
    MODAL_OPEN
} from &amp;quot;./modalConstants&amp;quot;;

import {createReducer} from &amp;quot;common/utils/reducerUtils&amp;quot;;

const initialState = null;

export function openModal(state, payload) {
    const {modalType, modalProps} = payload;
    return {modalType, modalProps};
}

export function closeModal(state, payload) {
    return null;
}

export default createReducer(initialState,  {
    [MODAL_OPEN] : openModal,
    [MODAL_CLOSE] : closeModal
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The reducer logic is trivial.  We&#39;re simply going to store an object that contains the name of the modal type and the props it should receive, and either set the value or clear it out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/21777d793eacd3863a04d71480f5a30618fb7ce2/src/features/modals/TestModal.jsx&#34;&gt;features/modals/TestModal.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import React, {Component} from &amp;quot;react&amp;quot;;
import {connect} from &amp;quot;react-redux&amp;quot;;
import {
    Modal,
} from &amp;quot;semantic-ui-react&amp;quot;;

import {closeModal} from &amp;quot;features/modals/modalActions&amp;quot;;

const actions = {closeModal};

export class TestModal extends Component {
    render() {
        return (
            &amp;lt;Modal
                closeIcon=&amp;quot;close&amp;quot;
                open={true}
                onClose={this.props.closeModal}
            &amp;gt;
                &amp;lt;Modal.Header&amp;gt;Modal #1&amp;lt;/Modal.Header&amp;gt;
                &amp;lt;Modal.Content image&amp;gt;
                    &amp;lt;Modal.Description&amp;gt;
                        &amp;lt;p&amp;gt;This is a modal dialog.  Pretty neat, huh?&amp;lt;/p&amp;gt;
                    &amp;lt;/Modal.Description&amp;gt;
                &amp;lt;/Modal.Content&amp;gt;
                &amp;lt;Modal.Actions&amp;gt;
                &amp;lt;/Modal.Actions&amp;gt;
            &amp;lt;/Modal&amp;gt;
        )
    }
}

export default connect(null, actions)(TestModal);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Semantic-UI-React conveniently has a &lt;code&gt;Modal&lt;/code&gt; class already, which allows you to render headers, content, and action buttons.  Since the focus of this article is on how to manipulate modals via React and Redux, and not specifically how to build them from scratch, we&#39;ll use the SUI-React &lt;code&gt;Modal&lt;/code&gt; class rather than trying to build our own.&lt;/p&gt;

&lt;p&gt;Note that we pass an &lt;code&gt;open={true}&lt;/code&gt; prop to &lt;code&gt;&amp;lt;Modal&amp;gt;&lt;/code&gt;.  That&#39;s because the SUI-React &lt;code&gt;Modal&lt;/code&gt; can be either opened or closed, and in our case, whenever we show a &lt;code&gt;&amp;lt;TestModal&amp;gt;&lt;/code&gt;, we want the inner &lt;code&gt;&amp;lt;Modal&amp;gt;&lt;/code&gt; to be displayed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/21777d793eacd3863a04d71480f5a30618fb7ce2/src/features/modals/ModalManager.jsx&#34;&gt;features/modals/ModalManager.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import React, {Component} from &amp;quot;react&amp;quot;;
import {connect} from &amp;quot;react-redux&amp;quot;;

import TestModal from &amp;quot;./TestModal&amp;quot;;

const modalComponentLookupTable = {
    TestModal
};

const mapState = (state) =&amp;gt; ({currentModal : state.modals});

export class ModalManager extends Component {
    render() {
        const {currentModal} = this.props;

        let renderedModal;

        if(currentModal) {
            const {modalType, modalProps = {}} = currentModal;
            const ModalComponent = modalComponentLookupTable[modalType];

            renderedModal = &amp;lt;ModalComponent {...modalProps} /&amp;gt;;
        }

        return &amp;lt;span&amp;gt;{renderedModal}&amp;lt;/span&amp;gt;
    }
}

export default connect(mapState)(ModalManager);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we get to the heart of the basic modal setup.  Let&#39;s take a step back first, though, and consider the theory behind this.&lt;/p&gt;

&lt;p&gt;In a typical object-oriented GUI toolkit, you might do something like &lt;code&gt;const myModal = new MyModal(); myModal.show()&lt;/code&gt;, and the modal class would be responsible for displaying itself somehow.  This is also true with things like jQuery-based UI plugins as well.  At that point, you have some &amp;quot;implicit state&amp;quot; in your application.  Your app is &amp;quot;showing a modal&amp;quot;, but there&#39;s no real way to track that this is happening beyond the fact that there&#39;s an instance of &lt;code&gt;MyModal&lt;/code&gt; that&#39;s been created, or - if this is a web app - the fact that there&#39;s extra elements appended to the page.  The &amp;quot;are we showing a modal?&amp;quot; state is implicitly &lt;code&gt;true&lt;/code&gt;, but not actually being tracked anywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With React (and even more so with Redux), you are encouraged to make as much of your state explicit as possible.&lt;/strong&gt;  That&#39;s why you frequently see apps that store a value like &lt;code&gt;requesting : true&lt;/code&gt;, because you can now specifically base UI behavior on the fact that there&#39;s an AJAX request in progress (like showing a loading spinner).  &lt;strong&gt;In our case, we want to explicitly track the fact that we&#39;re showing a modal, and even more than that, a description of what the current modal is.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;&amp;lt;ModalManager&amp;gt;&lt;/code&gt; component will live near the top of the app&#39;s component tree.  It reads the current modal description from Redux.  If there&#39;s a description object, we need to actually show a modal.&lt;/p&gt;

&lt;p&gt;We create a lookup table where the keys are some string identifier, and the values are modal components.  In this case, we&#39;re just using the variable name as the key (via ES6 object literal shorthand syntax), so if &lt;code&gt;modalType&lt;/code&gt; is &lt;code&gt;&amp;quot;TestModal&amp;quot;&lt;/code&gt;, that&#39;s the component class we&#39;ll retrieve.  Once we have the right modal component class in a variable, we can use normal JSX syntax to render that component.  We can also take whatever props object was included in the description, and pass that to the modal.&lt;/p&gt;

&lt;p&gt;Here&#39;s what the result looks like:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-07-practical-redux-part-10/basic-single-modal.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-07-practical-redux-part-10/basic-single-modal.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;A modal!  With a backdrop!  Isn&#39;t this exciting? :)&lt;/p&gt;

&lt;p&gt;Code-wise, that&#39;s really all there is to this idea.  Use some descriptive value to decide when you should show a modal, and if so, which one, then render it and pass in whatever props it&#39;s supposed to have.  But, we can expand on this idea in a lot of useful ways.&lt;/p&gt;

&lt;h3 id=&#34;making-modals-stackable&#34;&gt;Making Modals Stackable&lt;/h3&gt;

&lt;p&gt;Most of the time, you &lt;em&gt;probably&lt;/em&gt; only need one modal open at once.  But, what if you actually &lt;em&gt;do&lt;/em&gt; need multiple modals open, stacked on top of each other?  Fortunately, now that we&#39;ve got the basic modal framework in place, this is pretty simple to add.  All we really need to do have our reducer store an array of modal descriptions instead of just one, and have the &lt;code&gt;ModalManager&lt;/code&gt; component render multiple modals in response.&lt;/p&gt;

&lt;p&gt;While we&#39;re at it, we can update our &lt;code&gt;TestModal&lt;/code&gt; component to actually make use of the new functionality.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/3cd4fd26023010a93b120380272c7b6a638f635d&#34;&gt;Commit 3cd4fd2: Implement stackable modals&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/3cd4fd26023010a93b120380272c7b6a638f635d/src/features/modals/modalReducer.js&#34;&gt;features/modals/modalReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;-const initialState = null;
+const initialState = [];

export function openModal(state, payload) {
    const {modalType, modalProps} = payload;
-   return {modalType, modalProps};
+   // Always pushing a new modal onto the stack
+   return state.concat({modalType, modalProps});
}

export function closeModal(state, payload) {
-   return null;
+   // Always popping the last modal off the stack
+   const newState = state.slice();
+   newState.pop();
+   return newState;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/3cd4fd26023010a93b120380272c7b6a638f635d/src/features/modals/ModalManager.jsx&#34;&gt;features/modals/ModalManager.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;const mapState = (state) =&amp;gt; ({currentModals : state.modals});

export class ModalManager extends Component {
    render() {
        const {currentModals} = this.props;

        const renderedModals = currentModals.map( (modalDescription, index) =&amp;gt; {
            const {modalType, modalProps = {}} = modalDescription;
            const ModalComponent = modalComponentLookupTable[modalType];

            return &amp;lt;ModalComponent {...modalProps}  key={modalType + index}/&amp;gt;;
        });

        return &amp;lt;span&amp;gt;{renderedModals}&amp;lt;/span&amp;gt;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Our &lt;code&gt;modalReducer&lt;/code&gt; cases switch to tracking a stack of modal descriptions in an array, and the &lt;code&gt;ModalManager&lt;/code&gt; component changes to loop over that array and render an array of modal components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/3cd4fd26023010a93b120380272c7b6a638f635d/src/features/modals/TestModal.jsx&#34;&gt;features/modals/TestModal.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {connect} from &amp;quot;react-redux&amp;quot;;
import {
    Modal,
+   Button,
} from &amp;quot;semantic-ui-react&amp;quot;;

-import {closeModal} from &amp;quot;features/modals/modalActions&amp;quot;;
+import {openModal, closeModal} from &amp;quot;features/modals/modalActions&amp;quot;;

-const actions = {closeModal};
+const actions = {openModal, closeModal};

export class TestModal extends Component {
+   onNextModalClick = () =&amp;gt; {
+       const {counter} = this.props;
+       this.props.openModal(&amp;quot;TestModal&amp;quot;, {counter : counter + 1});
+   }

    render() {
+       const {counter, closeModal} = this.props;

        return (
            &amp;lt;Modal
                closeIcon=&amp;quot;close&amp;quot;
                open={true}
-               onClose={this.props.closeModal}
+               onClose={closeModal}
            &amp;gt;
-               &amp;lt;Modal.Header&amp;gt;Modal #1&amp;lt;/Modal.Header&amp;gt;
+               &amp;lt;Modal.Header&amp;gt;Modal #{counter}&amp;lt;/Modal.Header&amp;gt;
                &amp;lt;Modal.Content image&amp;gt;
                    &amp;lt;Modal.Description&amp;gt;
-                       &amp;lt;p&amp;gt;This is a modal dialog.  Pretty neat, huh?&amp;lt;/p&amp;gt;
+                       &amp;lt;h4&amp;gt;
+                           Value from props:
+                       &amp;lt;/h4&amp;gt;
+                       &amp;lt;div&amp;gt;
+                           counter = {counter}
+                       &amp;lt;/div&amp;gt;
+                       &amp;lt;div&amp;gt;
+                           &amp;lt;Button onClick={this.onNextModalClick}&amp;gt;Add Another Modal&amp;lt;/Button&amp;gt;
+                       &amp;lt;/div&amp;gt;
                    &amp;lt;/Modal.Description&amp;gt;
                &amp;lt;/Modal.Content&amp;gt;
                &amp;lt;Modal.Actions&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Our &lt;code&gt;TestModal&lt;/code&gt; gets changed in two ways.  First, we&#39;ll take the &lt;code&gt;props.counter&lt;/code&gt; value and display it as part of the header and the descriptive text.  Then, we&#39;ll add a button and handle clicks on it by dispatching an action to show &lt;em&gt;another&lt;/em&gt; modal on top of the current one.  To illustrate that we&#39;re stacking them, we increase the counter value and pass it as a prop for the next modal in the stack.&lt;/p&gt;

&lt;p&gt;Let&#39;s try it out!  If we click the &amp;quot;Show Test Modal&amp;quot; button in the Tools menu, and then click &amp;quot;Add Another Modal&amp;quot; a few times, here&#39;s what we get (I temporarily added &lt;code&gt;dimmer={false}&lt;/code&gt; to &lt;code&gt;TestModal&lt;/code&gt; to keep the entire page from being blacked out):&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-07-practical-redux-part-10/multiple-stacked-modals.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-07-practical-redux-part-10/multiple-stacked-modals.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;Looks neat, and we&#39;ve proven that we can show modals on the screen.  Now, let&#39;s move on to building something useful.&lt;/p&gt;

&lt;h2 id=&#34;building-a-reusable-color-picker-dialog&#34;&gt;Building a Reusable Color Picker Dialog&lt;/h2&gt;

&lt;p&gt;Military units usually have some kind of a logo or way to visually identify themselves.  Right now, our fictional Battletech units only store a name and a faction affiliation.  Let&#39;s add a field for a color as well.&lt;/p&gt;

&lt;p&gt;If we&#39;re going to have a color field, we need some way to actually let the user pick the color.  And &lt;em&gt;obviously&lt;/em&gt;, if we&#39;re going to have a color picker, it should go in a modal dialog! :)  (See previous comments about deliberate over-engineering.)&lt;/p&gt;

&lt;p&gt;We&#39;ll need to build an input to show what the current color is and trigger the color picker dialog, as well as the dialog itself.&lt;/p&gt;

&lt;h3 id=&#34;creating-the-colorpickerdialog&#34;&gt;Creating the ColorPickerDialog&lt;/h3&gt;

&lt;p&gt;We&#39;ve already got the ability to show a modal, so we only need to create a new modal component class that renders some kind of color picker component.  We&#39;ll use the &lt;a href=&#34;http://casesandberg.github.io/react-color/&#34;&gt;React-Color&lt;/a&gt; library, which provides a variety of color pickers in various styles.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/9c6166efd9c6cfc861f7821eea8774e2565bf807&#34;&gt;Commit 9c6166e: Add React-Color library&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ColorPickerDialog&lt;/code&gt; itself will be very simple.  We just need to track some kind of color value in its state, pass that to the color picker component when we render, and update the state when the user selects a different color.  We&#39;ll also want to accept a callback prop that we can pass the new color to when the modal is closed successfully.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/a035b81ba0d055862b434153588cf817aac3461c&#34;&gt;Commit a035b81: Add an initial ColorPickerDialog&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/a035b81ba0d055862b434153588cf817aac3461c/src/common/components/ColorPickerDialog.jsx&#34;&gt;common/components/ColorPickerDialog.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import React, {Component} from &amp;quot;react&amp;quot;;
import {connect} from &amp;quot;react-redux&amp;quot;;
import {
    Modal,
    Button,
} from &amp;quot;semantic-ui-react&amp;quot;;

import {SketchPicker} from &amp;quot;react-color&amp;quot;;

import {closeModal} from &amp;quot;features/modals/modalActions&amp;quot;;
import {noop} from &amp;quot;common/utils/clientUtils&amp;quot;;

const actions = {closeModal};

export class ColorPickerDialog extends Component {
    constructor(props) {
        super();
        this.state = {
            color : props.color
        }
    }

    onSelectClicked = () =&amp;gt; {
        this.props.colorSelected(this.state.color);

        this.props.closeModal();
    }

    onSelectedColorChanged = (colorEvent) =&amp;gt; {
        this.setState({color : colorEvent.hex});
    }

    render() {
        const {closeModal} = this.props;

        return (
            &amp;lt;Modal
                closeIcon=&amp;quot;close&amp;quot;
                open={true}
                onClose={closeModal}
                size=&amp;quot;small&amp;quot;
            &amp;gt;
                &amp;lt;Modal.Header&amp;gt;Select Color&amp;lt;/Modal.Header&amp;gt;
                &amp;lt;Modal.Content&amp;gt;
                    &amp;lt;SketchPicker
                        color={this.state.color}
                        onChangeComplete={this.onSelectedColorChanged}
                    /&amp;gt;
                &amp;lt;/Modal.Content&amp;gt;
                &amp;lt;Modal.Actions&amp;gt;
                    &amp;lt;Button positive onClick={this.onSelectClicked}&amp;gt;Select&amp;lt;/Button&amp;gt;
                    &amp;lt;Button secondary onClick={closeModal}&amp;gt;Cancel&amp;lt;/Button&amp;gt;
                &amp;lt;/Modal.Actions&amp;gt;
            &amp;lt;/Modal&amp;gt;
        )
    }
}

ColorPickerDialog.defaultProps = {
    color : &amp;quot;red&amp;quot;,
    colorSelected : noop
};

export default connect(null, actions)(ColorPickerDialog);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Pretty straightforward.  We copy the initial color value from props to state in the constructor, and have all future changes apply to the component state.  (We also added the &lt;code&gt;ColorPickerDialog&lt;/code&gt; to the lookup table in &lt;code&gt;ModalManager&lt;/code&gt; as well.)&lt;/p&gt;

&lt;p&gt;Here&#39;s what it looks like if we show it:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-07-practical-redux-part-10/color-picker-dialog.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-07-practical-redux-part-10/color-picker-dialog.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;(Yes, the fact that the modal is so much bigger than the color picker component annoys me, but the Semantic-UI modal layouts don&#39;t seem to have much flexibility in size, and I don&#39;t feel like messing with this.)&lt;/p&gt;

&lt;p&gt;Now that we have a dialog, we also need an input to show the current color:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/ee3c0273c3e4284059584885328f65e86f1c73d4&#34;&gt;Commit ee3c027: Add a simple ColorPickerButton&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/ee3c0273c3e4284059584885328f65e86f1c73d4/src/common/components/ColorPickerButton.jsx&#34;&gt;common/components/ColorPickerButton.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import React from &amp;quot;react&amp;quot;;

import {Button} from &amp;quot;semantic-ui-react&amp;quot;;

const ColorPickerButton = ({value, onClick, disabled=false}) =&amp;gt; {
    return (
        &amp;lt;Button
            type=&amp;quot;button&amp;quot;
            style={{padding: &amp;quot;4px&amp;quot;, margin: 0}}
            disabled={disabled}
            onClick={onClick}
        &amp;gt;
            &amp;lt;div
                style={{
                    width : 30,
                    height : 15,
                    backgroundColor : value
                }}
            /&amp;gt;
        &amp;lt;/Button&amp;gt;
    )
}

export default ColorPickerButton;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We take a standard SUI-React &lt;code&gt;Button&lt;/code&gt;, and put a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; in the middle to show the current color value.&lt;/p&gt;

&lt;p&gt;We also need to actually add a color value to our store, and can use the &lt;code&gt;ColorPickerButton&lt;/code&gt; to show that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/07ead5b417149a397f9d04bf4a46c163b7f010da&#34;&gt;Commit 07ead5b: Add color field to unit info sample data and reducer&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/07ead5b417149a397f9d04bf4a46c163b7f010da/src/features/unitInfo/unitInfoReducer.js&#34;&gt;features/unitInfo/unitInfoReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;const initialState = {
    name : &amp;quot;N/A&amp;quot;,
    affiliation : &amp;quot;&amp;quot;,
+   color : &amp;quot;blue&amp;quot;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/07ead5b417149a397f9d04bf4a46c163b7f010da/src/features/unitInfo/UnitInfo/UnitInfo.jsx&#34;&gt;features/unitInfo/UnitInfo/UnitInfo.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import FormEditWrapper from &amp;quot;common/components/FormEditWrapper&amp;quot;;
+import ColorPickerButton from &amp;quot;common/components/ColorPickerButton&amp;quot;;

// skip ahead

    render() {
        const {unitInfo, updateUnitInfo} = this.props;
-       const {name, affiliation} = unitInfo;
+       const {name, affiliation, color} = unitInfo;

        return (
            &amp;lt;Segment attached=&amp;quot;bottom&amp;quot;&amp;gt;

// skip ahead
+                   &amp;lt;Form.Field name=&amp;quot;color&amp;quot;&amp;gt;
+                       &amp;lt;label&amp;gt;Color&amp;lt;/label&amp;gt;
+                       &amp;lt;ColorPickerButton value={color} /&amp;gt;
+                   &amp;lt;/Form.Field&amp;gt;
                &amp;lt;/Form&amp;gt;
            &amp;lt;/Segment&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We should now see our &lt;code&gt;ColorPickerButton&lt;/code&gt; onscreen:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-07-practical-redux-part-10/color-picker-button.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-07-practical-redux-part-10/color-picker-button.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;And finally, we need to hook up the &lt;code&gt;ColorPickerDialog&lt;/code&gt; so that it is shown when we click the &lt;code&gt;ColorPickerButton&lt;/code&gt;.  While we&#39;re at it, let&#39;s move the two color components into a separate subfolder so that we also have a place to put some Redux-related files:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/ede7d5c0b6d9dc700a2b2f234117a04557ae4ef1&#34;&gt;Commit ede7d5c: Move ColorPicker components into a separate folder&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/8ad59aabc2121718c49b4e040d34fa9a243e23b0&#34;&gt;Commit 8ad59aa: Connect UnitInfo color button to show the ColorPickerDialog&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/8ad59aabc2121718c49b4e040d34fa9a243e23b0/src/common/components/ColorPicker/colorPickerActions.js&#34;&gt;common/components/ColorPicker/colorPickerActions.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {
    openModal
} from &amp;quot;features/modals/modalActions&amp;quot;;

export function showColorPicker(initialColor) {
    return openModal(&amp;quot;ColorPickerDialog&amp;quot;, {color : initialColor});
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/8ad59aabc2121718c49b4e040d34fa9a243e23b0/src/features/unitInfo/UnitInfo/UnitInfo.jsx&#34;&gt;features/unitInfo/UnitInfo/UnitInfo.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {updateUnitInfo} from &amp;quot;../unitInfoActions&amp;quot;;
+import {showColorPicker} from &amp;quot;common/components/ColorPicker/colorPickerActions&amp;quot;;
import {getValueFromEvent} from &amp;quot;common/utils/clientUtils&amp;quot;;

const actions = {
    updateUnitInfo,
+   showColorPicker,
};

// skip ahead

+   onColorClicked = () =&amp;gt; {
+       this.props.showColorPicker(this.props.unitInfo.color);
+   }

    render() {
        const {unitInfo, updateUnitInfo} = this.props;

// skip ahead

                    &amp;lt;Form.Field name=&amp;quot;color&amp;quot;&amp;gt;
                        &amp;lt;label&amp;gt;Color&amp;lt;/label&amp;gt;
-                       &amp;lt;ColorPickerButton value={color} /&amp;gt;
+                       &amp;lt;ColorPickerButton
+                           value={color}
+                           onClick={this.onColorClicked}
+                       /&amp;gt;
                    &amp;lt;/Form.Field&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And with that, clicking on the color button in the Unit Info tab should now show our color picker with the current color that&#39;s in the store.  Progress!&lt;/p&gt;

&lt;h3 id=&#34;using-the-dialog-result-value&#34;&gt;Using the Dialog Result Value&lt;/h3&gt;

&lt;p&gt;Unfortunately, now we have a problem.  We can forward the current color value to the &lt;code&gt;ColorPickerDialog&lt;/code&gt; as part of the &amp;quot;description&amp;quot; that we&#39;re storing in state, and use that as the initial color value in the dialog.  &lt;strong&gt;However, we need some way to not only retrieve the final color value when the user clicks the &amp;quot;Select&amp;quot; button, but also actually use it to update the right field in the unit info reducer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The obvious solution is to simply pass a callback function as another prop to the dialog, but that means we&#39;d be storing the callback function in the Redux store.&lt;/strong&gt;  Per the Redux FAQ, &lt;a href=&#34;http://redux.js.org/docs/faq/OrganizingState.html#organizing-state-non-serializable&#34;&gt;putting non-serializable values in the store should be avoided&lt;/a&gt;.  Now, at the technical level, doing this &lt;em&gt;would&lt;/em&gt; work, but it would likely cause issues with time-travel debugging.  &lt;strong&gt;It&#39;s also not the &amp;quot;right&amp;quot; way to do things with Redux.&lt;/strong&gt;  So, what can we do instead?&lt;/p&gt;

&lt;p&gt;Earlier, I linked a previous post I&#39;d written on &lt;a href=&#34;https://blog.isquaredsoftware.com/2016/11/posts-on-packtpub-generic-redux-modals-and-building-better-bundles/&#34;&gt;handling return values from generic &amp;quot;picker&amp;quot; modals&lt;/a&gt;.  The basic idea is to &lt;strong&gt;have the code that requested the modal also include a pre-built action object as a prop for the dialog.  When the dialog succeeds, it dispatches that pre-built action, with its &amp;quot;return value&amp;quot; attached.&lt;/strong&gt;  It &lt;em&gt;is&lt;/em&gt; a level of indirection, but it allows us to continue following the Redux principles.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/2bfcd6e329f47051cd9e1809addfa5cef6bc4048&#34;&gt;Commit 2bfcd6e: Allow ColorPicker to dispatch pre-built actions after selection&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/2bfcd6e329f47051cd9e1809addfa5cef6bc4048/src/common/components/ColorPicker/colorPickerActions.js&#34;&gt;common/components/ColorPicker/colorPickerActions.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import _ from &amp;quot;lodash&amp;quot;;

import { openModal } from &amp;quot;features/modals/modalActions&amp;quot;;

export function showColorPicker(initialColor, onColorPickedAction) {
    // Define props that we want to &amp;quot;pass&amp;quot; to the ColorPicker dialog,
    // including the body of the action that should be dispatched when
    // the dialog is actually used to select a color.
    const colorPickerProps = {
        color : initialColor,
        onColorPicked : onColorPickedAction
    };
    return openModal(&amp;quot;ColorPickerDialog&amp;quot;, colorPickerProps);
}

export function colorSelected(color, actionToDispatch) {
    return (dispatch) =&amp;gt; {
        if(actionToDispatch) {
            const newAction = _.cloneDeep(actionToDispatch);
            newAction.payload.color = color;

            dispatch(newAction);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We update the &lt;code&gt;showColorPicker()&lt;/code&gt; action creator to take a second argument - the action that the caller wants dispatched upon success.  We also add a thunk that the dialog can call to handle dispatching that arbitrary action.  In the process, we also clone the entire action object just to be really sure that we&#39;re not accidentally mutating whatever &lt;code&gt;payload&lt;/code&gt; is.  (It&#39;s probably not necessary given how this is likely to be called, but it won&#39;t hurt to clone the action here.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/2bfcd6e329f47051cd9e1809addfa5cef6bc4048/src/common/components/ColorPicker/ColorPickerDialog.jsx&#34;&gt;common/components/ColorPicker/ColorPickerDialog.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {closeModal} from &amp;quot;features/modals/modalActions&amp;quot;;
-import {noop} from &amp;quot;common/utils/clientUtils&amp;quot;;
+import {colorSelected} from &amp;quot;./colorPickerActions&amp;quot;;

-const actions = {closeModal};
+const actions = {closeModal, colorSelected};

export class ColorPickerDialog extends Component {

// skip ahead
    onSelectClicked = () =&amp;gt; {
-       this.props.colorSelected(this.state.color);
+       this.props.colorSelected(this.state.color, this.props.onColorPicked);
        this.props.closeModal();
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We update the click handler to call &lt;code&gt;props.colorSelected()&lt;/code&gt; with both the new color value and the previously-supplied action object.&lt;/p&gt;

&lt;p&gt;Now, all we need to do is have the &lt;code&gt;UserInfo&lt;/code&gt; component pass along an appropriate action when we click the color button, and have a reducer case to handle that action.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/c0baa2f2843d0c023901fbd355a3a1aae8e93a3e&#34;&gt;Commit c0baa2f: Implement logic to set the unit color from a ColorPicker&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/c0baa2f2843d0c023901fbd355a3a1aae8e93a3e/src/features/unitInfo/unitInfoActions.js&#34;&gt;features/unitInfo/unitInfoActions.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;-import {UNIT_INFO_UPDATE} from &amp;quot;./unitInfoConstants&amp;quot;;
+import {
+   UNIT_INFO_UPDATE,
+   UNIT_INFO_SET_COLOR,
+} from &amp;quot;./unitInfoConstants&amp;quot;;

export function updateUnitInfo(values) {
    return {
        type : UNIT_INFO_UPDATE,
        payload : values,
    };
}

+export function setUnitColor(color) {
+   return {
+       type : UNIT_INFO_SET_COLOR,
+       payload : {color}
+   };
+}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&#39;ve mostly skipped showing action creators to save space in the posts, but we&#39;ll show the &lt;code&gt;setUnitColor()&lt;/code&gt; action creator just to emphasize that it&#39;s a simple action creator, nothing special at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/c0baa2f2843d0c023901fbd355a3a1aae8e93a3e/src/features/unitInfo/unitInfoReducer.js&#34;&gt;features/unitInfo/unitInfoReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;-function setUnitColor(state, payload) {
+   const {color} = payload;
+
+   return {
+       ...state,
+       color
+   };
+}

export default createReducer(initialState, {
    [DATA_LOADED] : dataLoaded,
    [UNIT_INFO_UPDATE] : updateUnitInfo,
+   [UNIT_INFO_SET_COLOR] : setUnitColor,
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The new case reducer is also very simple - we extract the new &lt;code&gt;color&lt;/code&gt; variable and apply that to our unit info state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/c0baa2f2843d0c023901fbd355a3a1aae8e93a3e/src/features/unitInfo/UnitInfo/UnitInfo.jsx&#34;&gt;features/unitInfo/UnitInfo/UnitInfo.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {selectUnitInfo} from &amp;quot;../unitInfoSelectors&amp;quot;;
-import {updateUnitInfo} from &amp;quot;../unitInfoActions&amp;quot;;
+import {updateUnitInfo, setUnitColor} from &amp;quot;../unitInfoActions&amp;quot;;
import {showColorPicker} from &amp;quot;common/components/ColorPicker/colorPickerActions&amp;quot;;
import {getValueFromEvent} from &amp;quot;common/utils/clientUtils&amp;quot;;

// skip ahead

    onColorClicked = () =&amp;gt; {
-       this.props.showColorPicker(this.props.unitInfo.color);
+       const onColorPickedAction = setUnitColor();
+
+       this.props.showColorPicker(this.props.unitInfo.color, onColorPickedAction);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And finally, we update the click handler for the color button.  We create our &amp;quot;pre-built&amp;quot; action using the &lt;code&gt;setUnitColor()&lt;/code&gt; action creator, but instead of dispatching it, we pass it to &lt;code&gt;showColorPicker()&lt;/code&gt; so it can be included as a prop to the &lt;code&gt;ColorPickerDialog&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let&#39;s try it out.  The color field in our sample data is &lt;code&gt;&amp;quot;blue&amp;quot;&lt;/code&gt;, while the default color prop to the &lt;code&gt;ColorPickerDialog&lt;/code&gt; is &lt;code&gt;&amp;quot;red&amp;quot;&lt;/code&gt;.  Let&#39;s try changing the color to something green, and confirm that it shows up in the color picker button in the unit info form:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-07-practical-redux-part-10/successful-color-selection.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-07-practical-redux-part-10/successful-color-selection.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;Success!  We were able to have the &lt;code&gt;UnitInfo&lt;/code&gt; component request that the dialog be shown, pass along its own pre-built action,  have the &lt;code&gt;ColorPickerDialog&lt;/code&gt; dispatch, and update the unit info state with the result value from the dialog.&lt;/p&gt;

&lt;h3 id=&#34;an-alternative-approach-to-dialog-results&#34;&gt;An Alternative Approach to Dialog Results&lt;/h3&gt;

&lt;p&gt;The Redux ecosystem includes libraries for almost every use case, and that includes modals.  There&#39;s &lt;a href=&#34;https://github.com/markerikson/redux-ecosystem-links/blob/master/widgets.md#modals&#34;&gt;a variety of existing libraries for Redux-connected modals available&lt;/a&gt;.  O&lt;strong&gt;ne particularly interesting library is &lt;a href=&#34;https://github.com/AKolodeev/redux-promising-modals&#34;&gt;redux-promising-modals&lt;/a&gt;&lt;/strong&gt;.  I haven&#39;t yet used it myself, but reading the docs, &lt;strong&gt;it appears to offer another valid solution to the question of handling return values from dialogs without breaking Redux principles&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;redux-promising-modals&lt;/code&gt; offers actions and a reducer for tracking open modals, very similar to what we just implemented (but does not include any components).  However, it also includes a middleware.  Whenever you dispatch a &lt;code&gt;PUSH_MODAL_WINDOW&lt;/code&gt; action, the middleware returns a promise, and tracks what modal that promise belongs to.  You can then use that promise in the code that called &lt;code&gt;dispatch()&lt;/code&gt;, and chain off of it.  When that modal is closed, the middleware extracts results from the action, and resolves the original promise, thus supplying the &amp;quot;return values&amp;quot; from the dialog.&lt;/p&gt;

&lt;p&gt;Here&#39;s an (untested) example of what using &lt;code&gt;redux-promising-modals&lt;/code&gt; might look like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {pushModal} from &amp;quot;redux-promising-modals&amp;quot;

function showColorPickerForUnitInfo(initialColor) {
    return (dispatch) =&amp;gt; {}
        dispatch(pushModal(&amp;quot;ColorPickerDialog&amp;quot;, {color : initialColor}))
            .then( (resultColor) =&amp;gt; {
                dispatch(setUnitInfoColor(resultColor));
            });
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To me, this looks like an excellent use of the Redux middleware pipeline for intercepting actions, and is a nicely pre-built solution to the problem of tracking open modals and handling modal return values.&lt;/p&gt;

&lt;h2 id=&#34;designing-a-context-menu-system&#34;&gt;Designing a Context Menu System&lt;/h2&gt;

&lt;p&gt;Now that we&#39;ve seen how to build a modal dialog system, we can apply the same principles to context menus.  &lt;strong&gt;A context menu is really just another modal that&#39;s probably absolutely positioned on screen, doesn&#39;t have a dimmer overlay behind it, and contains just a menu instead of a titlebar, content area, and action buttons.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This might be a good time to go back and review a couple of the concepts around how modals in React can actually get shown on screen.&lt;/p&gt;

&lt;h3 id=&#34;react-portals&#34;&gt;React Portals&lt;/h3&gt;

&lt;p&gt;We start our React applications by calling &lt;code&gt;ReactDOM.render(&amp;lt;App /&amp;gt;, rootElement)&lt;/code&gt;.  All of the nested HTML elements created by our React components are appended inside of that root element, in a single render tree.  However, this can make showing modals a little bit awkward.  especially if a very deeply nested child component wants to show a modal.  That nested component can render a &lt;code&gt;&amp;lt;Modal open={true} /&amp;gt;&lt;/code&gt;, but now the HTML generated by the &lt;code&gt;Modal&lt;/code&gt; component is going to be appended inside of the nested component.  That means it probably won&#39;t show up correctly on top of the rest of the UI.&lt;/p&gt;

&lt;p&gt;Now, sure, we can do some funky CSS stuff and make those elements pop out somehow, but there&#39;s a specific technique that&#39;s commonly used to make modals in React show up overlaid on the page contents.  That technique is called a &amp;quot;portal&amp;quot;.  &lt;strong&gt;A &amp;quot;portal&amp;quot; is when a React component uses its lifecycle methods to start a second React render tree, usually appended to the page body.  That way a nested component can render a &lt;code&gt;&amp;lt;Modal&amp;gt;&lt;/code&gt;, but the modal content pops out on top of the page.&lt;/strong&gt;  React actually supports this with a semi-official method called &lt;code&gt;ReactDOM.unstable_renderSubtreeIntoContainer&lt;/code&gt;.  (Note that in React 16, this method will be replaced with a newer version called &lt;code&gt;unstable_createPortal&lt;/code&gt;).  The &lt;a href=&#34;https://github.com/tajo/react-portal&#34;&gt;react-portal&lt;/a&gt; library wraps up that API to make it easier to use, and Semantic-UI-React&#39;s &lt;code&gt;Modal&lt;/code&gt; component also uses that method.&lt;/p&gt;

&lt;p&gt;Digging around the Semantic-UI-React docs and source, it looks like they do have that functionality broken out into a separate &lt;code&gt;Portal&lt;/code&gt; component, so we could use that.  But, for the sake of illustration, we&#39;ll use the &lt;code&gt;react-portal&lt;/code&gt; library instead to help implement our context menu system.&lt;/p&gt;

&lt;h3 id=&#34;building-the-context-menu-system&#34;&gt;Building the Context Menu System&lt;/h3&gt;

&lt;p&gt;Looking back at our description of what a &amp;quot;context menu&amp;quot; is, we said that it needs to be absolutely positioned on the screen.  We can put together a generic component to help render something at an absolute position.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/e7c1cb36e38db45df4c633f806a83fa1e00fbe18&#34;&gt;Commit e7c1cb3: Add an AbsolutePosition component&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/e7c1cb36e38db45df4c633f806a83fa1e00fbe18/src/common/components/AbsolutePosition.jsx&#34;&gt;common/components/AbsolutePosition.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import React from &amp;quot;react&amp;quot;;
import PropTypes from &amp;quot;prop-types&amp;quot;;

const AbsolutePosition = (props) =&amp;gt; {
    const {children, nodeRef} = props;
    const style = {
        position: &#39;absolute&#39;,
        top: props.top,
        bottom : props.bottom,
        left: props.left,
        right : props.right,
        width: props.width,
    };

    return (
        &amp;lt;div style={style} className={props.className} ref={nodeRef}&amp;gt;
            {children}
        &amp;lt;/div&amp;gt;
    );
}

AbsolutePosition.propTypes = {
    top: PropTypes.number,
    bottom : PropTypes.number,
    left: PropTypes.number,
    width: PropTypes.number,
    nodeRef : PropTypes.func,
};

export default AbsolutePosition;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;All we really do here is set a &lt;code&gt;div&lt;/code&gt;&#39;s style to &lt;code&gt;position : &amp;quot;absolute&amp;quot;&lt;/code&gt;, apply the provided positions, and insert the children inside the div.  The only slightly unusual thing here is that we&#39;re taking a prop called &lt;code&gt;nodeRef&lt;/code&gt;, and passing it down as a callback ref to the &lt;code&gt;div&lt;/code&gt;.  We&#39;ll see why that matters in a minute.&lt;/p&gt;

&lt;p&gt;Now for the actual context menu behavior.  First, we&#39;ll add the &lt;code&gt;react-portal&lt;/code&gt; library to our app:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/18de585532edc42fff5be0ad795c28e8df6e5fe7&#34;&gt;Commit 18de585: Add the React-Portal library&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then, we&#39;ll implement the core of our context menu functionality, very similar to how we built the &lt;code&gt;ModalManager&lt;/code&gt; component and reducer logic earlier.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/4fc3f4d88c03a22c4b817b71f97935ea324a1d22&#34;&gt;Commit 4fc3f4d: Implement core context menu handling logic&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/4fc3f4d88c03a22c4b817b71f97935ea324a1d22/src/features/contextMenus/contextMenuReducer.js&#34;&gt;features/contextMenus/contextMenuReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {createReducer} from &amp;quot;common/utils/reducerUtils&amp;quot;;

import {
    CONTEXT_MENU_SHOW,
    CONTEXT_MENU_HIDE,
} from &amp;quot;./contextMenuConstants&amp;quot;;

const contextMenuInitialState = {
    show : false,
    location : {
        x : null,
        y : null,
    },
    type : null,
    menuArgs : undefined,
}

function showContextMenu(state, payload) {
    return {
        ...state,
        show : true,
        ...payload
    };
}

function hideContextMenu(state, payload) {
    return {
        ...contextMenuInitialState
    }
};

export default createReducer(contextMenuInitialState, {
    [CONTEXT_MENU_SHOW] : showContextMenu,
    [CONTEXT_MENU_HIDE] : hideContextMenu
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Our &lt;code&gt;contextMenuReducer&lt;/code&gt; is fairly similar to the first iteration of the modal reducer.  I probably could have done almost the same thing, where &lt;code&gt;null&lt;/code&gt; represents no context menu and a valid object represents actually showing a menu, but wound up implementing this a bit differently in a couple ways.  (Not entirely sure why, either, but I did :) )&lt;/p&gt;

&lt;p&gt;We&#39;re going to track a &lt;code&gt;show&lt;/code&gt; flag that indicates whether we&#39;re showing a menu, and &lt;code&gt;type&lt;/code&gt; and &lt;code&gt;menuArgs&lt;/code&gt; represent the same concepts as with our modals.  We also need to track the location on screen where the menu should be positioned.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/4fc3f4d88c03a22c4b817b71f97935ea324a1d22/src/features/contextMenus/ContextMenu.jsx&#34;&gt;features/contextMenus/ContextMenu.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import React, {Component} from &amp;quot;react&amp;quot;;
import {connect} from &amp;quot;react-redux&amp;quot;;

import AbsolutePosition from &amp;quot;common/components/AbsolutePosition&amp;quot;;

import {hideContextMenu} from &amp;quot;./contextMenuActions&amp;quot;;

const actions = {hideContextMenu};

export class ContextMenu extends Component {
    componentDidMount() {
        document.addEventListener(&#39;click&#39;, this.handleClickOutside, true);
    }

    componentWillUnmount() {
        document.removeEventListener(&#39;click&#39;, this.handleClickOutside, true);
    }

    handleClickOutside = (e) =&amp;gt; {
        if (!this.node || !this.node.contains(e.target) ) {
            this.props.hideContextMenu();
        }
    }

    render() {
        const {location} = this.props;

        return (
            &amp;lt;AbsolutePosition
                left={location.x + 2}
                top={location.y}
                className=&amp;quot;contextMenu&amp;quot;
                nodeRef={node =&amp;gt; this.node = node}
            &amp;gt;
                {this.props.children}
            &amp;lt;/AbsolutePosition&amp;gt;
        )
    }
}

export default connect(null, actions)(ContextMenu);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next up we have a generic wrapper component for context menus.  This component takes care of listening for clicks outside the menu and calling a close function, as well as using an &lt;code&gt;&amp;lt;AbsolutePosition&amp;gt;&lt;/code&gt; component to put the menu in the right spot.  Note that we offset the &lt;code&gt;x&lt;/code&gt; coordinate by a couple pixels just to have the menu appear slightly offset from underneath the cursor.  Finally, note that we use the &lt;code&gt;nodeRef&lt;/code&gt; prop for &lt;code&gt;AbsolutePosition&lt;/code&gt;.  That&#39;s because we need to do some DOM checks to see if a click on the document is inside or outside the menu.  Since the &lt;code&gt;ContextMenu&lt;/code&gt; component doesn&#39;t render any actual HTML itself, it needs to have the &lt;code&gt;AbsolutePosition&lt;/code&gt; component &amp;quot;forward a ref&amp;quot; on down.  This is a useful technique, and &lt;a href=&#34;https://github.com/reactjs/react-redux/pull/270#issuecomment-175217424&#34;&gt;Dan Abramov wrote an example of the &amp;quot;forwarded refs&amp;quot; pattern a while back&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/4fc3f4d88c03a22c4b817b71f97935ea324a1d22/src/features/contextMenus/ContextMenuManager.jsx&#34;&gt;features/contextMenus/ContextMenuManager.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import React, {Component} from &amp;quot;react&amp;quot;;
import {connect} from &amp;quot;react-redux&amp;quot;;
import Portal from &#39;react-portal&#39;;

import ContextMenu from &amp;quot;./ContextMenu&amp;quot;;

import {selectContextMenu} from &amp;quot;./contextMenuSelectors&amp;quot;;

const menuTypes = {
};

export function contextMenuManagerMapState(state) {
    return {
        contextMenu : selectContextMenu(state)
    };
}

export class ContextMenuManager extends Component {
    render() {
        const {contextMenu} = this.props;
        const {show, location, type, menuArgs = {}} = contextMenu;

        let menu = null;

        if(show) {
            let MenuComponent = menuTypes[type];

            if(MenuComponent) {
                menu = (
                    &amp;lt;Portal isOpened={true}&amp;gt;
                        &amp;lt;ContextMenu location={location}&amp;gt;
                            &amp;lt;MenuComponent {...menuArgs} /&amp;gt;
                        &amp;lt;/ContextMenu&amp;gt;
                    &amp;lt;/Portal&amp;gt;
                )
            }
        }

        return menu;
    }
}

export default connect(contextMenuManagerMapState)(ContextMenuManager);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Similar to our &lt;code&gt;ModalManager&lt;/code&gt; component, the &lt;code&gt;ContextMenuManager&lt;/code&gt; uses the description in Redux to look up the right menu component if appropriate, and renders it.  In this case, we also surround the menu component with our &lt;code&gt;&amp;lt;ContextMenu&amp;gt;&lt;/code&gt; component to put it in the right position and handle clicks outside of it, and surround that with a &lt;code&gt;&amp;lt;Portal&amp;gt;&lt;/code&gt; to ensure that it floats over the UI.&lt;/p&gt;

&lt;p&gt;Next up, we add the &lt;code&gt;contextMenuReducer&lt;/code&gt; and the &lt;code&gt;ContextMenuManager&lt;/code&gt; to our root reducer and the core application layout:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/f38f38bbf02a8e947d9750e950fcf67972eccf7d&#34;&gt;Commit f38f38b: Add the context menu reducer and component to the app&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And we can now throw together a quick test menu component to verify that this is working (including adding it to the context menu lookup table):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/958a2c310870686965187a766d9c4eb2875e5af8&#34;&gt;Commit 958a2c3: Add an initial test context menu component and hook it up&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/958a2c310870686965187a766d9c4eb2875e5af8/src/features/contextMenus/TestContextMenu.jsx&#34;&gt;features/contextMenus/TestContextMenu.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import React, { Component } from &#39;react&#39;
import { Menu } from &#39;semantic-ui-react&#39;

export default class TestContextMenu extends Component {
    render() {
        return (
            &amp;lt;Menu vertical&amp;gt;
                &amp;lt;Menu.Item&amp;gt;
                    &amp;lt;Menu.Header&amp;gt;Menu Header: {this.props.text} &amp;lt;/Menu.Header&amp;gt;
                    &amp;lt;Menu.Menu&amp;gt;
                        &amp;lt;Menu.Item&amp;gt;First Menu Item&amp;lt;/Menu.Item&amp;gt;
                        &amp;lt;Menu.Item&amp;gt;Second Menu Item&amp;lt;/Menu.Item&amp;gt;
                    &amp;lt;/Menu.Menu&amp;gt;
                &amp;lt;/Menu.Item&amp;gt;
            &amp;lt;/Menu&amp;gt;
        )
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we click our &amp;quot;Show Test Context Menu&amp;quot; button, here&#39;s what we should see:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-07-practical-redux-part-10/test-context-menu.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-07-practical-redux-part-10/test-context-menu.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;Yay, a menu!  That does nothing useful!&lt;/p&gt;

&lt;h3 id=&#34;adding-a-context-menu-to-the-pilots-list&#34;&gt;Adding a Context Menu to the Pilots List&lt;/h3&gt;

&lt;p&gt;The majority of &lt;strong&gt;&lt;em&gt;Project Mini-Mek&lt;/em&gt;&lt;/strong&gt;&#39;s functionality thus far has involved the &amp;quot;Pilots&amp;quot; tab, so we&#39;ll work with that.  We&#39;ve already added the ability to select a current pilot from the list, and delete a pilot, so let&#39;s add a context menu that offers that capability as well.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/70208eae474ba5744b7fbec926d5eed690ac5310&#34;&gt;Commit 70208ea: Implement a context menu for pilots list items&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/70208eae474ba5744b7fbec926d5eed690ac5310/src/features/pilots/PilotsList/PilotsListItemMenu.jsx&#34;&gt;features/pilots/PilotsList/PilotsListItemMenu.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import React, { Component } from &#39;react&#39;
import {connect} from &amp;quot;react-redux&amp;quot;;
import { Menu } from &#39;semantic-ui-react&#39;

import {selectPilot} from &amp;quot;../pilotsActions&amp;quot;;
import {deleteEntity} from &amp;quot;features/entities/entityActions&amp;quot;;
import {hideContextMenu} from &amp;quot;features/contextMenus/contextMenuActions&amp;quot;;

const actions = {
    selectPilot,
    deleteEntity,
    hideContextMenu,
}

export class PilotsListItemMenu extends Component {
    onSelectClicked = () =&amp;gt; {
        this.props.selectPilot(this.props.pilotId);
        this.props.hideContextMenu();
    }

    onDeleteClicked = () =&amp;gt; {
        this.props.deleteEntity(&amp;quot;Pilot&amp;quot;, this.props.pilotId);
        this.props.hideContextMenu();
    }

    render() {
        return (
            &amp;lt;Menu vertical&amp;gt;
                &amp;lt;Menu.Item&amp;gt;
                    &amp;lt;Menu.Header&amp;gt;Pilot: {this.props.text} &amp;lt;/Menu.Header&amp;gt;
                    &amp;lt;Menu.Menu&amp;gt;
                        &amp;lt;Menu.Item onClick={this.onSelectClicked}&amp;gt;Select Pilot&amp;lt;/Menu.Item&amp;gt;
                        &amp;lt;Menu.Item onClick={this.onDeleteClicked}&amp;gt;Delete Pilot&amp;lt;/Menu.Item&amp;gt;
                    &amp;lt;/Menu.Menu&amp;gt;
                &amp;lt;/Menu.Item&amp;gt;
            &amp;lt;/Menu&amp;gt;
        )
    }
}

export default connect(null, actions)(PilotsListItemMenu);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Our pilots menu will take two props: the ID of a pilot, and some text that will be the name of the pilot that was clicked on.  We show the pilot name in the header, and use &lt;code&gt;props.pilotId&lt;/code&gt; to tell the action creators what pilot to select or delete.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/70208eae474ba5744b7fbec926d5eed690ac5310/src/features/pilots/PilotsList/PilotsListRow.jsx&#34;&gt;features/pilots/PilotsList/PilotsListRow.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {getEntitiesSession} from &amp;quot;features/entities/entitySelectors&amp;quot;;
+import {deleteEntity} from &amp;quot;features/entities/entityActions&amp;quot;;
import {showContextMenu} from &amp;quot;features/contextMenus/contextMenuActions&amp;quot;;

const actions = {
    deleteEntity,
+   showContextMenu,
};


-const PilotsListRow = ({pilot={}, onPilotClicked=_.noop, selected, deleteEntity}) =&amp;gt; {
+const PilotsListRow = ({pilot={}, onPilotClicked=_.noop, selected, deleteEntity, showContextMenu}) =&amp;gt; {
    const {
        id = null,
        name = &amp;quot;&amp;quot;,


// skip ahead

+   const onRowRightClicked = (e) =&amp;gt; {
+       e.preventDefault();
+       e.stopPropagation();
+
+       const {pageX, pageY} = e;
+       showContextMenu(pageX, pageY, &amp;quot;PilotsListItemMenu&amp;quot;, {text: pilot.name, pilotId : id});
+   }

    return (
-       &amp;lt;Table.Row onClick={onRowClicked} active={selected}&amp;gt;
+       &amp;lt;Table.Row onClick={onRowClicked} onContextMenu={onRowRightClicked}  active={selected}&amp;gt;
            &amp;lt;Table.Cell&amp;gt;
                {name}
            &amp;lt;/Table.Cell&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Over in the &lt;code&gt;PilotsListRow&lt;/code&gt; component, we&#39;ll add a right-click handler on the entire row, and use the click coordinates in the page as the x/y location values for showing the menu.  We also pass along the pilot name and ID values to the menu.&lt;/p&gt;

&lt;p&gt;It&#39;s worth noting that the &lt;code&gt;PilotsListRow&lt;/code&gt; component is a functional component that now has a lot going on inside of it.  Frankly, it probably ought to be converted to a class component at this point, but I haven&#39;t yet gotten around to doing that.  We may try to do that next time.&lt;/p&gt;

&lt;p&gt;With that menu implemented, let&#39;s try it out:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-07-practical-redux-part-10/pilots-list-menu.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-07-practical-redux-part-10/pilots-list-menu.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;h3 id=&#34;fixing-some-existing-bugs&#34;&gt;Fixing Some Existing Bugs&lt;/h3&gt;

&lt;p&gt;In the process of adding this menu, I &lt;em&gt;did&lt;/em&gt; actually find a couple bugs in the pilots list behavior (&lt;strong&gt;gasp!&lt;/strong&gt;).  We&#39;d better go ahead and fix those now.&lt;/p&gt;

&lt;p&gt;Both of these bugs occur when you take certain steps while there is a pilot selected.  You can reproduce the first bug with these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select a pilot and make some edits&lt;/li&gt;
&lt;li&gt;While still editing, select another pilot (either by left-clicking the row, or right-clicking the row and choosing &amp;quot;Select Pilot&amp;quot; from our new context menu).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You&#39;ll see that when a different pilot is selected, the work-in-progress edits are actually applied to the pilot, which isn&#39;t what we want.  Selecting another pilot should &lt;em&gt;canceL&lt;/em&gt; the edits entirely, not apply them.&lt;/p&gt;

&lt;p&gt;The second bug can be reproduced by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start editing a pilot&lt;/li&gt;
&lt;li&gt;Delete that pilot&lt;/li&gt;
&lt;li&gt;Observe that the &amp;quot;Start Editing&amp;quot; button is still active, even though there&#39;s no longer a pilot visibly selected&lt;/li&gt;
&lt;li&gt;Click &amp;quot;Start Editing&amp;quot;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You&#39;ll see our shiny new error overlay pop up with an error saying that &lt;code&gt;Error: Pilot instance with id 6 not found&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let&#39;s go ahead and fix both of those.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/08af9489fcdfe136b384044cb55bd337895b2410&#34;&gt;Commit 08af948: Fix a pair of bugs with pilot selection and editing&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/08af9489fcdfe136b384044cb55bd337895b2410/src/features/pilots/pilotsActions.js&#34;&gt;features/pilots/pilotsActions.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;export function selectPilot(pilotID) {
    return (dispatch, getState) =&amp;gt; {
        const state = getState();
        const isEditing = selectIsEditingPilot(state);

        if(isEditing) {
-           dispatch(stopEditingPilot());
+           dispatch(cancelEditingPilot())
        }

        dispatch({
            type : PILOT_SELECT,
            payload : {currentPilot : pilotID},
        });
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The first bug is really silly and stupid.  In the case where we select a pilot while already editing, I was dispatching &lt;code&gt;stopEditingPilot()&lt;/code&gt;, which is the action creator that &lt;em&gt;applies&lt;/em&gt; our edits.  We actually need to dispatch &lt;code&gt;cancelEditingPilot()&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/08af9489fcdfe136b384044cb55bd337895b2410/src/features/pilots/pilotsReducer.js&#34;&gt;features/pilots/pilotsReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;export function stopEditingIfDeleted(state, payload) {
    const {itemType, itemID} = payload;
    const {isEditing, currentPilot} = state;

-   if(isEditing &amp;amp;&amp;amp; itemType === &amp;quot;Pilot&amp;quot; &amp;amp;&amp;amp; itemID === currentPilot) {
-       return stopEditingPilot(state, payload);
+   if(itemType === &amp;quot;Pilot&amp;quot; &amp;amp;&amp;amp; itemID === currentPilot) {
+       return {
+           ...state,
+           isEditing : false,
+           currentPilot : null
+       }
    }

    return state;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The bug with the &lt;code&gt;currentPilot&lt;/code&gt; field not clearing out is simply a logic error in our &lt;code&gt;pilotsReducer&lt;/code&gt;.  We were attempting to handle the case of a pilot being deleted while already being edited, by listening for the &lt;code&gt;ENTITY_DELETE&lt;/code&gt; action and checking to see if the entity was of type &amp;quot;Pilot&amp;quot; and matched the selected pilot ID.  But, we were &lt;em&gt;only&lt;/em&gt; checking that pilot ID if we were editing,  We really need to handle &lt;em&gt;any&lt;/em&gt; time the currently selected pilot is deleted, and do so by clearing out both the &lt;code&gt;currentPilot&lt;/code&gt; and &lt;code&gt;isEditing&lt;/code&gt; fields.&lt;/p&gt;

&lt;h2 id=&#34;final-thoughts&#34;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;Hopefully those examples have shown you how to implement your own modal handling using React and Redux.  Those same techniques can be applied to drive other parts of your UI as well.  For example, it&#39;s very straightforward to implement popup toast notifications using this approach.&lt;/p&gt;

&lt;p&gt;Be sure to tune in next time, when we&#39;ll... ah... actually, I&#39;m not sure what I&#39;ll tackle for the next part :)  I have &lt;a href=&#34;https://gist.github.com/markerikson/840fc9baf9598971ae252b92ac832955&#34;&gt;several more ideas for things I want to cover in this series&lt;/a&gt;, but I haven&#39;t yet decided what topic I&#39;m going to cover next.  If you&#39;ve got any preferences for which topic I should write about next, please let me know in the comments or on Twitter!&lt;/p&gt;

&lt;h2 id=&#34;further-information&#34;&gt;Further Information&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;React Modals and Portals&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://daveceddia.com/open-modal-in-react/&#34;&gt;Modal Dialogs in React&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/35623656/how-can-i-display-a-modal-dialog-in-redux-that-performs-asynchronous-actions/35641680&#34;&gt;Stack Overflow: How to control modal dialogs using Redux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://codeburst.io/modals-in-react-f6c3ff9f4701&#34;&gt;Modals in React (tradeoffs and approaches)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://codersmind.com/scalable-modals-react-redux/&#34;&gt;Scalable Modals with React and Redux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/2016/11/posts-on-packtpub-generic-redux-modals-and-building-better-bundles/&#34;&gt;Generic Picker Modals with Redux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/react-redux-links/blob/master/react-component-patterns.md#modal-dialogs&#34;&gt;React/Redux Links: React Component Patterns - Modal Dialogs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/react-redux-links/blob/master/redux-techniques.md#ui-and-widget-implementations&#34;&gt;React/Redux Links: Redux Techniques - UI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/reactjs/react-redux/pull/270#issuecomment-175217424&#34;&gt;Dan Abramov explains the &amp;quot;Forwarded Refs&amp;quot; pattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;React and Redux Modal Tools&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/tajo/react-portal&#34;&gt;react-portal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/AKolodeev/redux-promising-modals&#34;&gt;redux-promising-modals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/redux-ecosystem-links/blob/master/widgets.md#modals&#34;&gt;Redux Addons Catalog: Widgets - Modals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/redux-ecosystem-links/blob/master/widgets.md#notifications&#34;&gt;Redux Addons Catalog: Widgets - Notifications&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    
    <item>
      <title>Practical Redux, Part 9: Upgrading Redux-ORM and Updating Dependencies</title>
      <link>https://blog.isquaredsoftware.com/2017/07/practical-redux-part-9-managing-dependencies/</link>
      <pubDate>Tue, 11 Jul 2017 10:00:00 -0400</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2017/07/practical-redux-part-9-managing-dependencies/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;

&lt;p&gt;Greetings, and welcome back to the Practical Redux series!  It&#39;s been a few months since the last post, but as promised, I still have a lot of topics I want to cover for this series.&lt;/p&gt;

&lt;p&gt;Picking up where we left off: &lt;strong&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/2017/01/practical-redux-part-8-form-draft-data-management/&#34;&gt;in Part 8&lt;/a&gt;&lt;/strong&gt;, we added the ability to delete Pilot entries, used our generic entity reducer logic to implement &amp;quot;draft data&amp;quot; handling for the Pilot editing form, and added the ability to cancel and reset form edits.  This time around, we have some housekeeping to do: we&#39;ll &lt;strong&gt;update Redux-ORM to 0.9 and discuss the migration and API changes, update our other dependencies to the latest versions, and look at ways to cache NPM dependencies for consistent project installation even if you&#39;re offline&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The code for this project is on Github at &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek&#34;&gt;github.com/markerikson/project-minimek&lt;/a&gt;&lt;/strong&gt;.  The original WIP commits I made for this post can be seen in &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/10&#34;&gt;PR #10: Practical Redux Part 9 WIP&lt;/a&gt;&lt;/strong&gt;, and the final &amp;quot;clean&amp;quot; commits can be seen in in &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/11&#34;&gt;PR #11: Practical Redux Part 9 Final&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I&#39;ll be linking to each &amp;quot;final&amp;quot; commit as I go through the post, as well as specific files in those commits.  I won&#39;t paste every changed file in here or show every single changed line, to save space, but rather try to show the most relevant changes for each commit as appropriate.&lt;/p&gt;

&lt;h3 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#using-redux-orm-0-9&#34;&gt;Using Redux-ORM 0.9&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#updating-dependencies&#34;&gt;Updating Dependencies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#managing-dependency-packages-for-offline-installation&#34;&gt;Managing Dependency Packages for Offline Installation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#final-thoughts&#34;&gt;Final Thoughts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#further-information&#34;&gt;Further Information&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;using-redux-orm-0-9&#34;&gt;Using Redux-ORM 0.9&lt;/h2&gt;

&lt;p&gt;When I started the series, the current version of Redux-ORM was 0.8.1.  Since then, there have been some noticeable changes.  Author Tommi Kaikkonen built and released version 0.9, which includes a number of breaking changes to the API and the library&#39;s behavior.  Sadly, he also no longer has time to maintain the library by himself, but a call for new maintainers resulted in a couple people being given full ownership of the library, and several others (including myself) were given commit rights.  So, Redux-ORM is definitely alive and well.&lt;/p&gt;

&lt;p&gt;Let&#39;s take a look at the major changes in Redux-ORM 0.9, then tackle upgrading &lt;strong&gt;&lt;em&gt;Project Mini-Mek&lt;/em&gt;&lt;/strong&gt; to use it.&lt;/p&gt;

&lt;h3 id=&#34;redux-orm-0-9-changes&#34;&gt;Redux-ORM 0.9 Changes&lt;/h3&gt;

&lt;p&gt;One of the nice things about the Redux-ORM library is its documentation.  Too many JS libraries have nothing more than a few example snippets in their README, but Redux-ORM has had a couple pretty good intro tutorials and decent API docs since the beginning.&lt;/p&gt;

&lt;p&gt;The Redux-ORM 0.9 changes included a helpful &lt;a href=&#34;https://github.com/tommikaikkonen/redux-orm/wiki/0.9-Migration-Guide&#34;&gt;migration guide for using 0.9&lt;/a&gt;.  Since that document is pretty good as-is, I won&#39;t try to restate everything, but I &lt;em&gt;will&lt;/em&gt; highlight the biggest changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The 0.8 &lt;code&gt;Schema&lt;/code&gt; class has been renamed to &lt;code&gt;ORM&lt;/code&gt;, due to conceptual changes in how it works internally.  Some of the Schema methods have been replaced:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;schema.from(state)&lt;/code&gt; is now &lt;code&gt;orm.from(state)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;schema.withMutations(state)&lt;/code&gt; is now &lt;code&gt;orm.mutableSession(state)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;schema.getDefaultState()&lt;/code&gt; is now &lt;code&gt;orm.getEmptyState()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Session&lt;/code&gt; instances now apply changes immediately, instead of queueing up changes to be applied when you called &lt;code&gt;session.reduce()&lt;/code&gt;.  That means that after any change, like &lt;code&gt;myModel.someField = 123&lt;/code&gt;, the &lt;code&gt;session.state&lt;/code&gt; object will have been correctly immutably updated to reflect the current values (so &lt;code&gt;session.state.MyModel.byId[id].someField&lt;/code&gt; would now be &lt;code&gt;123&lt;/code&gt; right away).  This simplifies complex reducer logic considerably, since you no longer have to worry about what updates are currently pending inside the session&#39;s queue and which have been applied.  This also means that the &lt;code&gt;session.state = session.reduce()&lt;/code&gt; trick I showed previously can be dropped, as the session basically does that for you automatically.&lt;/li&gt;
&lt;li&gt;The prior APIs for creating an entities reducer and selectors from a schema have been moved into separate functions.  I haven&#39;t yet used any of those myself, in either this series or elsewhere.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;QuerySet&lt;/code&gt; &amp;quot;flag&amp;quot; properties for &lt;code&gt;someQuerySet.withModels&lt;/code&gt; and &lt;code&gt;someQuerySet.withRefs&lt;/code&gt; have been removed, and you should now use &lt;code&gt;toModelArray()&lt;/code&gt; or &lt;code&gt;toRefArray()&lt;/code&gt; instead.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;QuerySet&lt;/code&gt;s are now lazy, so you can chain them together and only execute when needed&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Model&lt;/code&gt; classes now can take declarations of expected field names.  In 0.8, &lt;code&gt;Model&lt;/code&gt; instances dynamically created ES5 properties for values that were in the underlying plain data object and for relational fields, each time an instance was built.  In 0.9, you can add field declarations to your model class, and Redux-ORM can more efficiently handle those.  (The field declarations are still optional if you prefer not to use them.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, 0.9.1 added a &lt;code&gt;Model.upsert()&lt;/code&gt; method.  As mentioned in &lt;a href=&#34;https://blog.isquaredsoftware.com/2016/10/practical-redux-part-2-redux-orm-concepts-and-techniques/&#34;&gt;Part 2&lt;/a&gt;, Redux-ORM didn&#39;t merge or de-duplicate items with the same ID the way Normalizr does.  I had &lt;a href=&#34;https://github.com/tommikaikkonen/redux-orm/issues/50&#34;&gt;opened up an issue to discuss possible fixes&lt;/a&gt;, and the new &lt;code&gt;upsert()&lt;/code&gt; method was added as a result.  So, calling &lt;code&gt;upsert()&lt;/code&gt; instead of &lt;code&gt;create()&lt;/code&gt; takes care of things nicely.&lt;/p&gt;

&lt;h3 id=&#34;upgrading-project-mini-mek-to-redux-orm-0-9&#34;&gt;Upgrading Project Mini-Mek to Redux-ORM 0.9&lt;/h3&gt;

&lt;p&gt;With those changes in mind, let&#39;s go ahead and migrate &lt;strong&gt;&lt;em&gt;Project Mini-Mek&lt;/em&gt;&lt;/strong&gt; to use the latest version of Redux-ORM.  At the time of writing, that&#39;s 0.9.4.  For this step, we&#39;ll update this version explicitly.  I played around with both &lt;code&gt;yarn add&lt;/code&gt; and &lt;code&gt;yarn upgrade&lt;/code&gt; a bit.  Both work, but &lt;code&gt;yarn upgrade&lt;/code&gt; seemed to lock the entry in &lt;code&gt;package.json&lt;/code&gt; to the given version even if I added the &lt;code&gt;^&lt;/code&gt; in front of it.  So, we&#39;ll do it with &lt;code&gt;add&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;yarn add redux-orm@0.9.4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That updates the contents of &lt;code&gt;node_modules/redux-orm&lt;/code&gt; and modifies our &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;yarn.lock&lt;/code&gt; files, so let&#39;s commit those:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/2dd60244fad786ec4a4b0008cfa795bf4ccde7de&#34;&gt;Commit 2dd6024: Update Redux-ORM to 0.9.4&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we can move on to actually modifying the application code to match.  Fortunately, the changes aren&#39;t overly complicated, and mostly break down into a few edits repeated several times.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/3c1994530b18c3195c95cf9e59c9b159a873209f&#34;&gt;Commit 3c19945: Update Redux-ORM usage to work with 0.9.x&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let&#39;s go through examples of each change:&lt;/p&gt;

&lt;p&gt;First, we need to replace creating a &lt;code&gt;Schema&lt;/code&gt; with an &lt;code&gt;ORM&lt;/code&gt; instead:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/3c1994530b18c3195c95cf9e59c9b159a873209f/src/app/schema/schema.js&#34;&gt;app/schema/schema.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;-import {Schema} from &amp;quot;redux-orm&amp;quot;;
+import {ORM } from &amp;quot;redux-orm&amp;quot;;

import Pilot from &amp;quot;features/pilots/Pilot&amp;quot;;
import MechDesign from &amp;quot;features/mechs/MechDesign&amp;quot;;
import Mech from &amp;quot;features/mechs/Mech&amp;quot;;

-const schema = new Schema();
-schema.register(Pilot, MechDesign, Mech);
+const orm = new ORM();
+orm.register(Pilot, MechDesign, Mech);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Second, we need to use &lt;code&gt;orm.getEmptyState()&lt;/code&gt;, our reducers that use a &lt;code&gt;Session&lt;/code&gt; should stop using &lt;code&gt;session.state = session.reduce()&lt;/code&gt;, and we should use &lt;code&gt;toModelArray()&lt;/code&gt; instead of &lt;code&gt;withModels&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/3c1994530b18c3195c95cf9e59c9b159a873209f/src/app/reducers/entitiesReducer.js&#34;&gt;app/reducers/entitiesReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {DATA_LOADED} from &amp;quot;features/tools/toolConstants&amp;quot;;

-import schema from &amp;quot;app/schema&amp;quot;
+import orm from &amp;quot;app/schema&amp;quot;

-const initialState = schema.getDefaultState();
+const initialState = orm.getEmptyState();

export function loadData(state, payload) {
    // Create a Redux-ORM session from our entities &amp;quot;tables&amp;quot;
-   const session = schema.from(state);
+   const session = orm.session(state);
    // Get a reference to the correct version of model classes for this Session
    const {Pilot, MechDesign, Mech} = session;

// skip ahead

    // Clear out any existing models from state so that we can avoid
    // conflicts from the new data coming in if data is reloaded
    [Pilot, Mech, MechDesign].forEach(modelType =&amp;gt; {
-       modelType.all().withModels.forEach(model =&amp;gt; model.delete());
-       session.state = session.reduce();
+       modelType.all().toModelArray().forEach(model =&amp;gt; model.delete());
    });

-   // Queue up creation commands for each entry
+   // Immutably update the session state as we insert items
    pilots.forEach(pilot =&amp;gt; Pilot.parse(pilot));

    designs.forEach(design =&amp;gt; MechDesign.parse(design));
    mechs.forEach(mech =&amp;gt; Mech.parse(mech));

-   // Apply the queued updates and return the updated &amp;quot;tables&amp;quot;
-   return session.reduce();
+   // Return the new &amp;quot;tables&amp;quot; object containing the updates
+   return session.state;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Third, our &lt;code&gt;Model&lt;/code&gt; classes should be updated to add declarations for the fields they contain, and we can replace uses of &lt;code&gt;create()&lt;/code&gt; with &lt;code&gt;upsert()&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/3c1994530b18c3195c95cf9e59c9b159a873209f/src/features/pilots/Pilot.js&#34;&gt;features/pilots/Pilot.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;-import {Model, fk} from &amp;quot;redux-orm&amp;quot;;
+import {Model, fk, attr} from &amp;quot;redux-orm&amp;quot;;

export default class Pilot extends Model {
    static get fields() {
        return {
+           id : attr(),
+           name : attr(),
+           rank : attr(),
+           gunnery : attr(),
+           piloting : attr(),
+           age : attr(),
            mech : fk(&amp;quot;Mech&amp;quot;),
        };
    }

    static parse(pilotData) {
        // We could do useful stuff in here with relations,
        // but since we have no relations yet, all we need
        // to do is pass the pilot data on to create() or upsert()

        // Note that in a static class method, `this` is the
        // class itself, not an instance
-       return this.create(pilotData)
+       return this.upsert(pilotData);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once we apply those edits consistently across the rest of the codebase, our application &lt;em&gt;should&lt;/em&gt; now run correctly with no errors.&lt;/p&gt;

&lt;p&gt;I haven&#39;t yet played with &lt;code&gt;upsert()&lt;/code&gt; all that much, but at the moment I don&#39;t see any real downside to using it pretty much anywhere in place of &lt;code&gt;create()&lt;/code&gt;.  Note that because we&#39;re now using it, you could actually copy and paste the &lt;code&gt;pilots.forEach(pilot =&amp;gt; Pilot.parse(pilot));&lt;/code&gt; line in &lt;code&gt;loadData()&lt;/code&gt;, and those Pilot entries would load okay.  You could also load a Pilot entry with an existing ID but a couple different values, and it &lt;em&gt;should&lt;/em&gt; be merged in correctly (only overwriting the changed values).&lt;/p&gt;

&lt;h2 id=&#34;updating-dependencies&#34;&gt;Updating Dependencies&lt;/h2&gt;

&lt;p&gt;The React world has continued to move forward over the last few months as well.  React is up to 15.6, Create-React-App hit the big 1.0 and is now at 1.0.10, and many other libs have been updated.  Since we&#39;re updating things, tt would be good to get everything else up to date too.&lt;/p&gt;

&lt;h3 id=&#34;updating-react-scripts&#34;&gt;Updating React-Scripts&lt;/h3&gt;

&lt;p&gt;As mentioned in &lt;a href=&#34;https://blog.isquaredsoftware.com/2016/12/practical-redux-part-5-loading-and-displaying-data/&#34;&gt;Part 5&lt;/a&gt;, Create-React-App is really just the CLI tool that sets up your initial project.  All the build system magic is taken care of inside the &lt;code&gt;react-scripts&lt;/code&gt; package, and we only need to update that one dependency to take advantage of the latest improvements.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;yarn add --dev react-scripts@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/c6621b34fe5415b3499cad9a445784c779a95f72&#34;&gt;Commit c6621b3: Update react-scripts to 1.0.10&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&#34;updating-other-dependencies&#34;&gt;Updating Other Dependencies&lt;/h3&gt;

&lt;p&gt;We&#39;ve got several other dependencies that need to be updated as well.  We could list them all in a single &lt;code&gt;yarn add&lt;/code&gt; or &lt;code&gt;yarn upgrade&lt;/code&gt; command, but maybe we don&#39;t want to actually just automatically bump them all to the latest versions.  Yarn includes a &lt;code&gt;upgrade-interactive&lt;/code&gt; command that shows us the latest versions of each one, and lets us pick and choose which ones to update:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-cmd&#34;&gt;project-minimek&amp;gt; yarn upgrade-interactive
yarn upgrade-interactive
? Choose which packages to update. (Press &amp;lt;space&amp;gt; to select, &amp;lt;a&amp;gt; to toggle all, &amp;lt;i&amp;gt; to inverse selection)
 dependencies
 ( ) lodash                    4.16.6        ?  4.17.4
 ( ) react                     15.3.2        ?  15.6.1
 ( ) react-dom                 15.3.2        ?  15.6.1
 ( ) react-redux               5.0.0-beta.3  ?  5.0.5
 ( ) react-toggle-display      2.1.1         ?  2.2.0
 ( ) redbox-react              1.3.3         ?  1.4.3
 ( ) redux                     3.6.0         ?  3.7.1
 ( ) redux-devtools-extension  1.0.0         ?  2.13.2
 ( ) redux-thunk               2.1.0         ?  2.2.0
 ( ) reselect                  2.5.4         ?  3.0.1
 ( ) semantic-ui-css           2.2.4         ?  2.2.10
 ( ) semantic-ui-react         0.61.1        ?  0.71.0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Having said that, we might as well go ahead and bump all of them to the latest versions after all.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/e179c95469d2050ffeae9ac9cb7f3d2eefd136c2&#34;&gt;Commit e179c95: Update app dependencies to current versions&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&#34;removing-the-custom-error-overlay&#34;&gt;Removing the Custom Error Overlay&lt;/h3&gt;

&lt;p&gt;When I first set up the &lt;a href=&#34;https://blog.isquaredsoftware.com/2016/11/practical-redux-part-3-project-planning-and-setup/&#34;&gt;support for Hot Module Replacement in Part 3&lt;/a&gt;, I used a library called Redbox-React to show error messages.  I&#39;ll temporarily throw an error inside a component&#39;s render method to show what it looks like:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-07-practical-redux-part-9/redbox-react-error-message.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-07-practical-redux-part-9/redbox-react-error-message.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;That helps, but it could be better.&lt;/p&gt;

&lt;p&gt;Since that time, Create-React-App has added a powerful and informative built-in error overlay.  All we need to do to make use of it is remove our own error handling code from &lt;code&gt;src/index.js&lt;/code&gt;.  While we&#39;re at it, we&#39;ll also remove the dependency on &lt;code&gt;redbox-react&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-cmd&#34;&gt;yarn remove redbox-react
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/9782e30e434a5b86a8e9ce8f57fe9af0138db2f4&#34;&gt;Commit 9782e30: Remove custom error overlay in favor of CRA&#39;s built-in overlay&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/9782e30e434a5b86a8e9ce8f57fe9af0138db2f4/src/index.js&#34;&gt;src/index.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;if(module.hot) {
-   // Support hot reloading of components
-   // and display an overlay for runtime errors
-   const renderApp = render;
-   const renderError = (error) =&amp;gt; {
-       const RedBox = require(&amp;quot;redbox-react&amp;quot;).default;
-       ReactDOM.render(
-           &amp;lt;RedBox error={error} /&amp;gt;,
-           rootEl,
-       );
-   };
-
-   // In development, we wrap the rendering function to catch errors,
-   // and if something breaks, log the error and render it to the screen
-   render = () =&amp;gt; {
-       try {
-           renderApp();
-       }
-       catch(error) {
-           console.error(error);
-           renderError(error);
-       }
-   };
-
+   // Support hot reloading of components.
    // Whenever the App component file or one of its dependencies
    // is changed, re-import the updated component and re-render it
    module.hot.accept(&amp;quot;./app/layout/App&amp;quot;, () =&amp;gt; {
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now if we throw the same error, the overlay looks like this:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-07-practical-redux-part-9/cra-error-message.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-07-practical-redux-part-9/cra-error-message.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;Ahhh... much more readable, informative, and soothing.  (Now all we need is &lt;a href=&#34;https://en.wikipedia.org/wiki/Phrases_from_The_Hitchhiker&#39;s_Guide_to_the_Galaxy#Don.27t_Panic&#34;&gt;a towel, and an electronic book with the words &amp;quot;Don&#39;t Panic&amp;quot; written on the front&lt;/a&gt;.)&lt;/p&gt;

&lt;h3 id=&#34;fixing-proptypes&#34;&gt;Fixing PropTypes&lt;/h3&gt;

&lt;p&gt;If we restart our dev server and re-run the page, Create-React-App prints out a warning:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-cmd&#34;&gt;Compiled with warnings.

./src/common/components/FormEditWrapper.jsx
  Line 1:  React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead  react/no-deprecated

Search for the keywords to learn more about each warning.
To ignore, add // eslint-disable-next-line to the line before.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As part of the preparation for React 16, the React team is working on splitting several capabilities out into separate packages.  This includes &lt;code&gt;React.createClass()&lt;/code&gt; and the &lt;code&gt;PropTypes&lt;/code&gt; API.  React 15.5 started showing warnings any time you try to use those out of the &lt;code&gt;&amp;quot;react&amp;quot;&lt;/code&gt; package,  Most of the major libraries in the React ecosystem have now been updated, but we need to do the same.  Fortunately, this is an easy change:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/8573ed7e62971017d0cf4d4116f43b964cf10aef&#34;&gt;Commit 8573ed7: Use prop-types lib instead of React.PropTypes&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/8573ed7e62971017d0cf4d4116f43b964cf10aef/src/common/components/FormEditWrapper.jsx&#34;&gt;common/components/FormEditWrapper.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;-import React, {Component, PropTypes} from &amp;quot;react&amp;quot;;
+import React, {Component} from &amp;quot;react&amp;quot;;
+import PropTypes from &amp;quot;prop-types&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we restart the server one more time, the warning should be gone.&lt;/p&gt;

&lt;h2 id=&#34;managing-dependency-packages-for-offline-installation&#34;&gt;Managing Dependency Packages for Offline Installation&lt;/h2&gt;

&lt;p&gt;Package managers are powerful tools.  With just a config file and a command, we can download all the dependencies our application needs.  Unfortunately, this also introduces many weaknesses and concerns.  What happens if the latest version of a package breaks something for me?  How can I know that I&#39;m getting the same package contents every time?  What if something happens to a package server, or I need to be able to install these packages offline?&lt;/p&gt;

&lt;p&gt;The infamous &lt;code&gt;left-pad&lt;/code&gt; incident and various Github outages have shown that these are very real questions.  While the use of hashes and locked URLs can ensure that a package manager like NPM is actually seeing the same file each time, that doesn&#39;t help if the network is down.&lt;/p&gt;

&lt;p&gt;There&#39;s been a few approaches suggested for handling NPM dependencies without needing a network connection.  Using NPM or Yarn&#39;s local per-machine cache works, but only if you&#39;ve downloaded the necessary packages on that machine before.  A number of people have suggested that you check in your entire &lt;code&gt;node_modules&lt;/code&gt; folder, but that&#39;s a &lt;em&gt;very&lt;/em&gt; bad idea for a variety of reasons.  That&#39;s potentially tens or hundreds of thousands of files taking up hundreds of megs on disk, AND that can include platform-specific binaries built post-install (like &lt;code&gt;node-sass&lt;/code&gt;&#39;s inclusion of &lt;code&gt;libsass&lt;/code&gt;).  If you check in your &lt;code&gt;node_modules&lt;/code&gt; on a Mac, there&#39;s a good chance that it won&#39;t work on Windows or Linux (and vice versa).&lt;/p&gt;

&lt;p&gt;The most ideal solution is to actually check in the downloaded archives for each package.  Since platform-specific artifacts like &lt;code&gt;libsass&lt;/code&gt; are built &lt;em&gt;after&lt;/em&gt; installation, you can safely clone a repo on any machine, install the packages from that per-repo cache, and have things built properly for that machine.&lt;/p&gt;

&lt;p&gt;Yarn includes an &amp;quot;offline mirror&amp;quot; feature built in.  As far as I know, NPM has not had this built in as a specific capability, but there&#39;s a third-party tool called &lt;a href=&#34;https://github.com/JamieMason/shrinkpack&#34;&gt;Shrinkpack&lt;/a&gt; that can use an NPM &amp;quot;shrinkwrap&amp;quot; file file as the basis for caching package tarballs in the repo.  Based on &lt;a href=&#34;https://twitter.com/acemarke/status/883441155035332608&#34;&gt;a recent Twitter conversation&lt;/a&gt;, it seems that this is also a future planned feature for a future NPM5 release, and that it&#39;s possible to sorta-kinda mimic that with a &lt;code&gt;.npmrc&lt;/code&gt; file and the &lt;code&gt;--prefer-offline&lt;/code&gt; flag for NPM right now.&lt;/p&gt;

&lt;p&gt;So, let&#39;s set up a package cache for Yarn to work with.  First, we need to create a &lt;code&gt;.yarnrc&lt;/code&gt; file in the repo:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/326f253d45faa65cef56330ef0afd82bc628d16a&#34;&gt;Commit 326f253: Add Yarn config file for an offline cache&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/326f253d45faa65cef56330ef0afd82bc628d16a/.yarnrc&#34;&gt;.yarnrc&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;yarn-offline-mirror &amp;quot;./offline-mirror&amp;quot;
yarn-offline-mirror-pruning true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We&#39;ll set two values.  &lt;code&gt;yarn-offline-mirror&lt;/code&gt; is the folder where we want Yarn to save the package tarballs.  By default, if you update package versions, Yarn will only add new files to that folder, but not remove outdated ones.  If we set &lt;code&gt;yarn-offline-mirror-prune&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;, it will also remove old package tarballs to match what&#39;s currently installed.&lt;/p&gt;

&lt;p&gt;Next, we need to actually force Yarn to reinstall everything.  The simplest way is to rename the &lt;code&gt;node_modules&lt;/code&gt; folder to something like &lt;code&gt;node_modules.bak&lt;/code&gt;, then run &lt;code&gt;yarn&lt;/code&gt; again.  Now, if you look inside the &lt;code&gt;offline-mirror&lt;/code&gt; older, you should see around 1000 archives, like &lt;code&gt;react-15.6.1.tgz&lt;/code&gt;.  We can &lt;code&gt;git add&lt;/code&gt; the entire folder, and check them all in:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/063e1bf71b10b9f2854e9390ed96ad4dcadc1291&#34;&gt;Commit XYZ: Commit dependency packages&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And with that, anyone else who is using Yarn along with this project &lt;em&gt;should&lt;/em&gt; be able to use exactly the same packages that I have right now, even if you try to install them while you&#39;re offline.  In theory, anyway.  For full disclosure, this is a feature that I&#39;ve only partly played with myself, and I&#39;ve actually spent the last couple days fighting Yarn trying to get a variation of this to cooperate in my project at work, without success.  (Nitty-gritty details at &lt;a href=&#34;https://github.com/yarnpkg/yarn/issues/3910&#34;&gt;yarn#3910&lt;/a&gt;.)  So, seems really useful, but YMMV in practice.&lt;/p&gt;

&lt;h2 id=&#34;final-thoughts&#34;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;This post was probably a lot less exciting than the last few parts, but in today&#39;s world, updating dependencies is a pretty important topic.  I&#39;m still learning a lot of these intricacies myself (and in some cases, actively struggling with the tools), so please don&#39;t take the steps I showed as absolute gospel.&lt;/p&gt;

&lt;p&gt;The good news is that we can now get back to writing code, adding features, and demonstrating useful techniques.  Next time, we&#39;ll look at how to implement Redux-driven modal dialogs and context menus.&lt;/p&gt;

&lt;h2 id=&#34;further-information&#34;&gt;Further Information&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Redux-ORM 0.9&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/tommikaikkonen/redux-orm/wiki/0.9-Migration-Guide&#34;&gt;Redux-ORM 0.9 Migration Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/tommikaikkonen/redux-orm-primer/compare/dc0a17d93bbfe4b5bc31a2042a73c6ca1a83190a...migrate_to_0_9&#34;&gt;Redux-ORM Primer 0.9 Migration Diff&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/tommikaikkonen/redux-orm/pull/62&#34;&gt;Redux-ORM PR #62: 0.9 implementation and major changes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/tommikaikkonen/redux-orm/issues/50&#34;&gt;Redux ORM #50: De-duplication of entries during item creation?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://tommikaikkonen.github.io/redux-orm/index.html&#34;&gt;Redux-ORM API docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create-React-App 1.0&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/facebookincubator/create-react-app/releases/tag/v1.0.0&#34;&gt;What&#39;s New in Create-React-App&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/facebookincubator/create-react-app/releases/tag/v1.0.0&#34;&gt;Create-React-App 1.0 release notes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Offline Package Caching&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/JamieMason/shrinkpack&#34;&gt;jamiemason/Shrinkpack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://yarnpkg.com/blog/2016/11/24/offline-mirror/&#34;&gt;Running Yarn offline&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://codeforcoffee.org/intro-to-yarn-and-offline-module-caching&#34;&gt;Introduction to Yarn and Offline Module Caching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://evbogue.com/distributednodepackages/&#34;&gt;How to live without NPM (using Yarn for distributed package management)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/acemarke/status/883441155035332608&#34;&gt;Twitter: future plans for caching with NPM5&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    
    <item>
      <title>Practical Redux, Part 8: Form Draft Data Management</title>
      <link>https://blog.isquaredsoftware.com/2017/01/practical-redux-part-8-form-draft-data-management/</link>
      <pubDate>Thu, 26 Jan 2017 23:00:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2017/01/practical-redux-part-8-form-draft-data-management/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/2017/01/practical-redux-part-7-forms-editing-reducers/&#34;&gt;In Part 7&lt;/a&gt;&lt;/strong&gt;, we used a custom FormEditWrapper component to buffer form change events, wrote custom reducer logic for the &amp;quot;editing&amp;quot; feature, and added basic editing for Pilot entries.  This time, we&#39;ll &lt;strong&gt;add the ability to delete Pilots, use generic entity reducer logic to implement &amp;quot;draft data&amp;quot; handling for forms, and implement form resetting and cancelation.&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The code for this project is on Github at &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek&#34;&gt;github.com/markerikson/project-minimek&lt;/a&gt;&lt;/strong&gt;.  The original WIP commits I made for this post can be seen in &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/8&#34;&gt;PR #8: Practical Redux Part 8 WIP&lt;/a&gt;&lt;/strong&gt;, and the final &amp;quot;clean&amp;quot; commits can be seen in in &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/9&#34;&gt;PR #9: Practical Redux Part 8 Final&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I&#39;ll be linking to each &amp;quot;final&amp;quot; commit as I go through the post, as well as specific files in those commits.  I won&#39;t paste every changed file in here or show every single changed line, to save space, but rather try to show the most relevant changes for each commit as appropriate.&lt;/p&gt;

&lt;h3 id=&#34;table-of-contents&#34;&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#deleting-pilot-entries&#34;&gt;Deleting Pilot Entries&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#managing-draft-data-for-forms&#34;&gt;Managing Draft Data for Forms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#generic-reducer-logic-for-editing-entities&#34;&gt;Generic Reducer Logic for Editing Entities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#using-draft-data-for-editing-pilots&#34;&gt;Using Draft Data for Editing Pilots&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#saving-form-edits&#34;&gt;Saving Form Edits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#resetting-and-canceling-form-edits&#34;&gt;Resetting and Canceling Form Edits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#final-thoughts&#34;&gt;Final Thoughts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#further-information&#34;&gt;Further Information&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;deleting-pilot-entries&#34;&gt;Deleting Pilot Entries&lt;/h2&gt;

&lt;p&gt;Thus far, we can load a list of Pilots from our fake API, display them in the UI, and edit the details of an individual pilot.  That covers two of the four capabilities in the term &amp;quot;CRUD&amp;quot; (&amp;quot;Create&amp;quot;, &amp;quot;Retrieve&amp;quot;, &amp;quot;Update&amp;quot;, and &amp;quot;Delete&amp;quot;).  Let&#39;s go ahead and &lt;strong&gt;implement the ability to delete Pilot entries from our state&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&#34;creating-a-redux-orm-session-selector&#34;&gt;Creating a Redux-ORM Session Selector&lt;/h3&gt;

&lt;p&gt;Before we implement the actual deletion capability, we&#39;ll do a bit of cleanup first, which will also give us a minor performance improvement.  As mentioned in &lt;a href=&#34;https://blog.isquaredsoftware.com/2017/01/practical-redux-part-6-connected-lists-forms-and-performance/&#34;&gt;in Part 6&lt;/a&gt;, &lt;strong&gt;many of our connected components create Redux-ORM Session instances in their &lt;code&gt;mapState&lt;/code&gt; functions&lt;/strong&gt;.  Creating these Session instances probably isn&#39;t &lt;em&gt;too&lt;/em&gt; expensive, but there really isn&#39;t a good reason to keep creating many Session instances every time the store updates and then throw them all away.  This is especially true because a Session instance wraps up a specific state &amp;quot;tables&amp;quot; object, and since all of our components will be doing reads and not writes, they could easily all do reads from the same Session instance with no problems.&lt;/p&gt;

&lt;p&gt;In addition, our &lt;code&gt;mapState&lt;/code&gt; functions are currently accessing &lt;code&gt;state.entities&lt;/code&gt; to pass that slice to the schema.  Explicitly accessing slices of state isn&#39;t &lt;em&gt;wrong&lt;/em&gt;, but &lt;strong&gt;it&#39;s good practice to use selector functions to encapsulate those lookups&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We can fix both of these issues at the same time, by &lt;strong&gt;creating a memoized selector function that will always return the same Session instance for a given version of the &lt;code&gt;entities&lt;/code&gt; state slice&lt;/strong&gt;.  (As a reminder, &amp;quot;memoization&amp;quot; means caching inputs and outputs, so that if you see the same inputs, you can skip the work and return the previously calculated output.)  The &lt;a href=&#34;https://github.com/reactjs/reselect&#34;&gt;Reselect&lt;/a&gt; library provides a function called &lt;code&gt;createSelector&lt;/code&gt; that will create the memoized selectors we need.  That way, we only create one Session instance per update to our Model data.  Again, our application is small enough that we probably wouldn&#39;t even see a difference in performance benchmarks, but it&#39;s a useful step in the right direction.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/42693a331fee1ff73594ff18e3833415655f7262&#34;&gt;Commit 42693a3: Use a selector to have only a single Session instance per state update&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/42693a331fee1ff73594ff18e3833415655f7262/src/features/entities/entitySelectors.js&#34;&gt;features/entities/entitySelectors.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {createSelector} from &amp;quot;reselect&amp;quot;;

import schema from &amp;quot;app/schema&amp;quot;;

export const selectEntities = state =&amp;gt; state.entities;

export const getEntitiesSession = createSelector(
    selectEntities,
    entities =&amp;gt; schema.from(entities)
);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The selector creation is simple.  We create an &amp;quot;input&amp;quot; selector that returns the &lt;code&gt;state.entities&lt;/code&gt; slice, and pass that as the first argument to the &lt;code&gt;createSelector&lt;/code&gt; function from &lt;a href=&#34;https://github.com/reactjs/reselect&#34;&gt;Reselect&lt;/a&gt;.  The &amp;quot;output&amp;quot; selector takes the returned entities slice, and calls &lt;code&gt;schema.from(entities)&lt;/code&gt; to create the Session instance.  &lt;strong&gt;That output selector will only run when the &lt;code&gt;entities&lt;/code&gt; object changes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;From there, we update all the connected components to use that selector:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/42693a331fee1ff73594ff18e3833415655f7262/src/features/pilots/PilotDetails/PilotDetails.jsx&#34;&gt;features/pilots/PilotDetails/PilotDetails.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {connect} from &amp;quot;react-redux&amp;quot;;
import {Form, Dropdown, Grid, Button} from &amp;quot;semantic-ui-react&amp;quot;;

-import schema from &amp;quot;app/schema&amp;quot;;
+import {getEntitiesSession} from &amp;quot;features/entities/entitySelectors&amp;quot;;

const mapState = (state) =&amp;gt; {
    let pilot;
    
    const currentPilot = selectCurrentPilot(state);
    
-   const session = schema.from(state.entities);    
+   const session = getEntitiesSession(state);
    const {Pilot} = session;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After updating all the components to use &lt;code&gt;getEntitiesSession()&lt;/code&gt;, we should only be creating a single Session instance per entities update.&lt;/p&gt;

&lt;h3 id=&#34;adding-entity-creation-and-deletion-reducers&#34;&gt;Adding Entity Creation and Deletion Reducers&lt;/h3&gt;

&lt;p&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/2017/01/practical-redux-part-7-forms-editing-reducers/&#34;&gt;In Part 7&lt;/a&gt;, we created a &amp;quot;feature reducer&amp;quot; to handle generic actions that apply to our &lt;code&gt;entities&lt;/code&gt; slice.  At the time, we only created a single case reducer, which responds to the &lt;code&gt;ENTITY_UPDATE&lt;/code&gt; action.  That allowed us to make updates to the Pilot entry that&#39;s being edited.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We&#39;re going to add two more case reducers to that section, one for creating new entities and one for deleting them&lt;/strong&gt;.  We need the deletion reducer now so that we can delete our Pilot entries, and the creation reducer will come into play a bit later.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/75cc30ab85b22b3af7f0a70d9a23a2d646833855&#34;&gt;Commit 75cc30a: Add generic entity creation and deletion handling&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/75cc30ab85b22b3af7f0a70d9a23a2d646833855/src/features/entities/entityReducer.js&#34;&gt;features/entities/entityReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;-import {ENTITY_UPDATE} from &amp;quot;./entityConstants&amp;quot;;
+import {
+   ENTITY_UPDATE,
+   ENTITY_DELETE,
+   ENTITY_CREATE,
+} from &amp;quot;./entityConstants&amp;quot;;

export function updateEntity(state, payload) {
    const {itemType, itemID, newItemAttributes} = payload;

    const session = schema.from(state);
    const ModelClass = session[itemType];

    let newState = state;

    if(ModelClass.hasId(itemID)) {
        const modelInstance = ModelClass.withId(itemID);

        modelInstance.update(newItemAttributes);

        newState = session.reduce();
    }

    return newState;
}

+export function deleteEntity(state, payload) {
+   const {itemID, itemType} = payload;
+
+   const session = schema.from(state);
+   const ModelClass = session[itemType];
+
+   let newState = state;
+
+   if(ModelClass.hasId(itemID)) {
+       const modelInstance = ModelClass.withId(itemID);
+
+       modelInstance.delete();
+
+       // Immutably apply updates and return the new entities structure
+       newState = session.reduce();
+   }
+
+   return newState;
+}
+
+export function createEntity(state, payload) {
+   const {itemType, newItemAttributes} = payload;
+
+   const session = schema.from(state);
+   const ModelClass = session[itemType];
+
+   ModelClass.parse(newItemAttributes);
+
+   const newState = session.reduce();
+   return newState;
+}
+

const entityHandlers = {
    [ENTITY_UPDATE] : updateEntity,
+   [ENTITY_CREATE] : createEntity,
+   [ENTITY_DELETE] : deleteEntity,
};

const entityCrudFeatureReducer = createConditionalSliceReducer(&amp;quot;entities&amp;quot;, entityHandlers);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;All of these reducers follow the same basic pattern: create a Redux-ORM session from the current state, look up a session-bound Model class by name, queue the appropriate update commands in Redux-ORM, then apply the updates immutably and return the updated state.  (Yes, it would probably be possible to write some kind of wrapper function that de-duplicates some of the common behavior in these functions, but they&#39;re short enough it&#39;s not worth the effort.)&lt;/p&gt;

&lt;p&gt;Note that the &lt;code&gt;createEntity()&lt;/code&gt; reducer expects that each Model class will have a static &lt;code&gt;parse()&lt;/code&gt; method.  Per &lt;a href=&#34;https://blog.isquaredsoftware.com/2016/12/practical-redux-part-5-loading-and-displaying-data/&#34;&gt;Part 5&lt;/a&gt;, that&#39;s not something that&#39;s built in to Redux-ORM, but rather a convention that we&#39;re following by writing those functions in all our Model classes.&lt;/p&gt;

&lt;h3 id=&#34;implementing-pilot-deletion&#34;&gt;Implementing Pilot Deletion&lt;/h3&gt;

&lt;p&gt;We should now be able to dispatch an &lt;code&gt;ENTITY_DELETE&lt;/code&gt; action to delete a given Pilot entry from the store.  All we need to do now is add delete buttons to our &lt;code&gt;PilotsListRow&lt;/code&gt; components, and hook them up to dispatch the action.&lt;/p&gt;

&lt;p&gt;We&#39;ll add another column to the Pilots list, and show a red circular X button for each row.  Clicking the button will delete the item.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/35e48d596189ab136f451b4691f2154a141e9b2c&#34;&gt;Commit 35e48d5: Add the ability to delete individual Pilot entries&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/35e48d596189ab136f451b4691f2154a141e9b2c/src/features/pilots/PilotsList/PilotsListHeader.jsx&#34;&gt;features/pilots/PilotsList/PilotsListHeader.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;-           &amp;lt;Table.HeaderCell width={4}&amp;gt;
+           &amp;lt;Table.HeaderCell width={3}&amp;gt;
                Mech
            &amp;lt;/Table.HeaderCell&amp;gt;
+           &amp;lt;Table.HeaderCell width={1} /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/35e48d596189ab136f451b4691f2154a141e9b2c/src/features/pilots/PilotsList/PilotsListRow.jsx&#34;&gt;features/pilots/PilotsList/PilotsListRow.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;-import {Table} from &amp;quot;semantic-ui-react&amp;quot;;
+import {
+    Table,
+    Button,
+    Icon,
+} from &amp;quot;semantic-ui-react&amp;quot;;


import {getEntitiesSession} from &amp;quot;features/entities/entitySelectors&amp;quot;;
+import {deleteEntity} from &amp;quot;features/entities/entityActions&amp;quot;;


+const actions = {
+    deleteEntity,
+};

-const PilotsListRow = ({pilot={}, onPilotClicked=_.noop, selected}) =&amp;gt; {
+const PilotsListRow = ({pilot={}, onPilotClicked=_.noop, selected, deleteEntity}) =&amp;gt; {

// Omit prop extraction

+   const onDeleteClicked = () =&amp;gt; deleteEntity(&amp;quot;Pilot&amp;quot;, id);

// Omit row cell rendering
            &amp;lt;Table.Cell&amp;gt;
                {mechType}
            &amp;lt;/Table.Cell&amp;gt;

+           &amp;lt;Table.Cell&amp;gt;
+               &amp;lt;Button
+                   compact
+                   basic
+                   circular
+                   size=&amp;quot;tiny&amp;quot;
+                   color=&amp;quot;red&amp;quot;
+                   icon={&amp;lt;Icon  name=&amp;quot;delete&amp;quot; /&amp;gt;}
+                   onClick={onDeleteClicked}
+               &amp;gt;
+               &amp;lt;/Button&amp;gt;
+           &amp;lt;/Table.Cell&amp;gt;
        &amp;lt;/Table.Row&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That should give us a column of delete buttons for all our Pilot entries:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-8/pilots-list-delete-buttons.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-8/pilots-list-delete-buttons.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;Clicking any of the delete buttons should remove the corresponding Pilot entry from the store, and that will result in the row being removed.  If you play around with things a bit, you&#39;ll see there&#39;s also some interesting behavior around trying to delete any Pilot entry while a Pilot is being edited, whether it&#39;s the same Pilot or a different Pilot.  Let&#39;s take a look at what&#39;s going on there.&lt;/p&gt;

&lt;h3 id=&#34;improving-the-pilot-deletion-logic&#34;&gt;Improving the Pilot Deletion Logic&lt;/h3&gt;

&lt;p&gt;Right now, &lt;em&gt;any&lt;/em&gt; click on the pilots list will dispatch the &lt;code&gt;PILOT_SELECT&lt;/code&gt; action, which also stops any active editing.  Let&#39;s update the logic so that it only stops editing if the current pilot is deleted.  There&#39;s probably a few different ways we could handle this.  We&#39;re going to do it with two distinct changes.&lt;/p&gt;

&lt;p&gt;First, we&#39;ll update the click handling in &lt;code&gt;&amp;lt;PilotsListRow&amp;gt;&lt;/code&gt;.  In the current code, a click on the delete button triggers the click handler for the button, but also triggers the click handler for the entire table row.  We&#39;ll have the button click handler cancel the event, so that the row handler doesn&#39;t get run afterwards.&lt;/p&gt;

&lt;p&gt;Second, we&#39;re going to have the pilots reducer listen for the &lt;code&gt;ENTITY_DELETE&lt;/code&gt; action type.  &lt;em&gt;If&lt;/em&gt; the deleted item is a Pilot, and we&#39;re in the middle of editing that pilot, we&#39;ll go ahead and stop editing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/d5da05b7951b9d1e50275f4b25d540d13699c93a&#34;&gt;Commit d5da05b: Only stop editing if the current pilot is deleted&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/d5da05b7951b9d1e50275f4b25d540d13699c93a/src/features/pilots/PilotsList/PilotsListRow.jsx&#34;&gt;features/pilots/PilotsList/PilotsListRow.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;-   const onDeleteClicked = () =&amp;gt; deleteEntity(&amp;quot;Pilot&amp;quot;, id);
+   const onDeleteClicked = (e) =&amp;gt; {
+       e.stopPropagation();
+       e.preventDefault();
+       deleteEntity(&amp;quot;Pilot&amp;quot;, id);
+   }

+   const onRowClicked = () =&amp;gt; onPilotClicked(id);


    return (
-       &amp;lt;Table.Row onClick={() =&amp;gt; onPilotClicked(id)} active={selected}&amp;gt;
+       &amp;lt;Table.Row onClick={onRowClicked} active={selected}&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/d5da05b7951b9d1e50275f4b25d540d13699c93a/src/features/pilots/pilotsReducer.js&#34;&gt;features/pilots/pilotsReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;+import {
+   ENTITY_DELETE,
+} from &amp;quot;features/entities/entityConstants&amp;quot;;

+export function stopEditingIfDeleted(state, payload) {
+   const {itemType, itemID} = payload;
+   const {isEditing, currentPilot} = state;
+
+   if(isEditing &amp;amp;&amp;amp; itemType === &amp;quot;Pilot&amp;quot; &amp;amp;&amp;amp; itemID === currentPilot) {
+       return stopEditingPilot(state, payload);
+   }
+
+   return state;
+}

export default createReducer(initialState, {
    [PILOT_SELECT] : selectPilot,
    [PILOT_EDIT_START] : startEditingPilot,
    [PILOT_EDIT_STOP] : stopEditingPilot,
+   [ENTITY_DELETE] : stopEditingIfDeleted,
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice that our &lt;code&gt;stopEditingIfDeleted&lt;/code&gt; function actually reuses the existing &lt;code&gt;stopEditingPilot&lt;/code&gt; function to do the work.  Also, &lt;strong&gt;this is another example of multiple reducers in different slices responding to the same action&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now if we edit one Pilot, and delete another, we&#39;ll stay in editing mode for the current pilot.  Selecting a different pilot will still cancel editing.&lt;/p&gt;

&lt;h2 id=&#34;managing-draft-data-for-forms&#34;&gt;Managing Draft Data for Forms&lt;/h2&gt;

&lt;p&gt;As mentioned in &lt;a href=&#34;https://blog.isquaredsoftware.com/2017/01/practical-redux-part-7-forms-editing-reducers/&#34;&gt;Part 7&lt;/a&gt;, our current Pilot editing logic updates the actual data object for that Pilot in the store.  Because both the list row and the edit form are referencing the same object, all edits in the form are immediately reflected in the list row.  That looks kinda cool when you first see it, but it&#39;s not really a desired behavior.  What if we wanted the user to be able to cancel the edits, or confirm they actually wanted to save the new values, or even reset the changes?&lt;/p&gt;

&lt;p&gt;I faced this issue when working on my own application.  It took me a while to figure out the approach I now use, although in hindsight, the idea sure &lt;em&gt;feels&lt;/em&gt; obvious, and I&#39;m kinda kicking myself for not working it out sooner.  (In my defense, it was still early on in my first actual usage of Redux.)  I also have to give a big shout-out and thanks to &lt;strong&gt;&lt;a href=&#34;https://twitter.com/tommikaikkonen&#34;&gt;Tommi Kaikkonen&lt;/a&gt;&lt;/strong&gt;, author of Redux-ORM, who took the time to listen to my use case, answer my questions, and help me work out the idea.&lt;/p&gt;

&lt;p&gt;I summarized the basic idea in the &lt;strong&gt;&lt;a href=&#34;http://redux.js.org/docs/recipes/reducers/NormalizingStateShape.html&#34;&gt;Structuring Reducers - Normalizing State Shape&lt;/a&gt;&lt;/strong&gt; section of the Redux docs.  I&#39;ll quote the relevant section here:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An application that does a lot of editing of entities might want to &lt;strong&gt;keep two sets of &amp;quot;tables&amp;quot; in the state, one for the &amp;quot;current&amp;quot; item values and one for the &amp;quot;work-in-progress/draft&amp;quot; item values. When an item is edited, its values could be copied into the &amp;quot;work-in-progress&amp;quot; section, and any actions that update it would be applied to the &amp;quot;work-in-progress&amp;quot; copy&lt;/strong&gt;, allowing the editing form to be controlled by that set of data while another part of the UI still refers to the original version. &amp;quot;Resetting&amp;quot; the edit form would simply require removing the item from the &amp;quot;work-in-progress&amp;quot; section and re-copying the original data from &amp;quot;current&amp;quot; to &amp;quot;work-in-progress&amp;quot;, while &amp;quot;applying&amp;quot; the edits would involve copying the values from the &amp;quot;work-in-progress&amp;quot; section to the &amp;quot;current&amp;quot; section.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This really goes back to one of the core concepts of both React and Redux:  &lt;strong&gt;whenever possible, represent your application&#39;s behavior through state&lt;/strong&gt;.  In this case, we want to have two different representations of the same item.  So, &lt;strong&gt;copy it, leave the original alone, and modify the copy&lt;/strong&gt;.  (This also applies to non-relational form data as well.)&lt;/p&gt;

&lt;h2 id=&#34;generic-reducer-logic-for-editing-entities&#34;&gt;Generic Reducer Logic for Editing Entities&lt;/h2&gt;

&lt;p&gt;Implementing this &amp;quot;draft slice&amp;quot; capability will require a noticeable amount of work.  We need to add this new &amp;quot;draft&amp;quot; state slice to our store, then write the reducer logic to actually copy items from our current &lt;code&gt;entities&lt;/code&gt; slice into the &amp;quot;draft&amp;quot; slice.&lt;/p&gt;

&lt;h3 id=&#34;adding-the-draft-state-slice&#34;&gt;Adding the Draft State Slice&lt;/h3&gt;

&lt;p&gt;The good news is that this first part is pretty easy.  We&#39;ve already got a small reducer in our core app folder that defines the &lt;code&gt;entities&lt;/code&gt; slice.  We just need to copy that reducer&#39;s initial state handling so that the &amp;quot;tables&amp;quot; are created for us, and add it in to the root reducer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/925d07796320c1000ca18d4520eeb54b3cb6ebc9&#34;&gt;Commit 925d077: Add an &amp;quot;editingEntities&amp;quot; state slice to store draft data&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/925d07796320c1000ca18d4520eeb54b3cb6ebc9/src/app/reducers/editingEntitiesReducer.js&#34;&gt;app/reducers/editingEntitiesReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {createReducer} from &amp;quot;common/utils/reducerUtils&amp;quot;;

import schema from &amp;quot;app/schema&amp;quot;;
const defaultEditingEntities = schema.getDefaultState();

export default createReducer(defaultEditingEntities, {
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This reducer will only define the initial shape of the state.  We won&#39;t add any actual update logic here - all that goes elsewhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/925d07796320c1000ca18d4520eeb54b3cb6ebc9/src/app/reducers/rootReducer.js&#34;&gt;app/reducers/rootReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt; import entitiesReducer from &amp;quot;./entitiesReducer&amp;quot;;
+import editingEntitiesReducer from &amp;quot;./editingEntitiesReducer&amp;quot;;
 import tabReducer from &amp;quot;features/tabs/tabReducer&amp;quot;;
 
const combinedReducer = combineReducers({
    entities : entitiesReducer,
+   editingEntities : editingEntitiesReducer,
    unitInfo : unitInfoReducer,
    pilots : pilotsReducer,
    mechs : mechsReducer,
    tabs : tabReducer,
}); 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We&#39;ll add &lt;code&gt;editingEntities&lt;/code&gt; as another top-level slice in our state tree.&lt;/p&gt;

&lt;p&gt;We&#39;ll also throw in a small utility function to simplify looking up a Model instance from a Session:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/dc83aebdab9b630c675e0f63e80319b78938752f&#34;&gt;Commit dc83aeb: Add a utility function to look up a model by type and ID&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/dc83aebdab9b630c675e0f63e80319b78938752f/src/common/utils/modelUtils.js&#34;&gt;common/utils/modelUtils.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;export function getModelByType(session, itemType, itemID) {
    const modelClass = session[itemType];
    const model = modelClass.withId(itemID);
    return model;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, we&#39;ll create our initial empty &amp;quot;editing feature&amp;quot; reducer.  Similar to how we defined the &amp;quot;generic entity CRUD&amp;quot; reducer, we&#39;ll add it to the end of the list of &amp;quot;top-level&amp;quot; reducers in our root reducer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/fbcad74c9d9b7ff6e2591324d9ca4c77a33fd49e&#34;&gt;Commit fbcad74: Create an empty editing feature reducer&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/fbcad74c9d9b7ff6e2591324d9ca4c77a33fd49e/src/features/editing/editingReducer.js&#34;&gt;features/editing/editingReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {createReducer} from &amp;quot;common/utils/reducerUtils&amp;quot;;

const editingFeatureReducer = createReducer({}, {
});

export default editingFeatureReducer;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/fbcad74c9d9b7ff6e2591324d9ca4c77a33fd49e/src/app/reducers/rootReducer.js&#34;&gt;app/reducers/rootReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import entityCrudReducer from &amp;quot;features/entities/entityReducer&amp;quot;;
+import editingFeatureReducer from &amp;quot;features/editing/editingReducer&amp;quot;;

const rootReducer = reduceReducers(
    combinedReducer,
    entityCrudReducer,
+   editingFeatureReducer,
);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Before we create the actual core reducer logic, we&#39;ll add some utility functions to encapsulate behavior.  We&#39;ll have a small function to update &lt;code&gt;state.entities&lt;/code&gt;, and another to update &lt;code&gt;state.editingEntities&lt;/code&gt;.  We&#39;ll also create a small function to access a given Redux-ORM Model instance, and ask it to copy its entire contents into a plain JS object:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/57b924ce9a25ce9daaf523b496ffadffedfebae7&#34;&gt;Commit 57b924c: Add editing utility functions&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/57b924ce9a25ce9daaf523b496ffadffedfebae7/src/features/editing/editingUtils.js&#34;&gt;features/editing/editingUtilities.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import schema from &amp;quot;app/schema&amp;quot;;
import {getModelByType} from &amp;quot;common/utils/modelUtils&amp;quot;;

export function updateEditingEntitiesState(state, updatedEditingEntities) {
    return {
        ...state,
        editingEntities : updatedEditingEntities,
    };
}

export function updateEntitiesState(state, updatedEntities) {
    return {
        ...state,
        entities : updatedEntities,
    };
}

export function readEntityData(entities, itemType, itemID) {
    const readSession = schema.from(entities);

    // Look up the model instance for the requested item
    const model = getModelByType(readSession, itemType, itemID);
    const data = model.toJSON();

    return data;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(Yes, those two &amp;quot;update&amp;quot; functions are trivial, and not &lt;em&gt;really&lt;/em&gt; needed here, but it&#39;s a small bit of encapsulation.)&lt;/p&gt;

&lt;p&gt;As we saw earlier with code that used &lt;code&gt;parse()&lt;/code&gt;, here we&#39;re expecting that all our Model instances will have a &lt;code&gt;toJSON()&lt;/code&gt; method.  Again, &lt;strong&gt;that&#39;s something we&#39;re writing ourselves as a common convention, not anything that&#39;s built in to Redux-ORM&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;On that note, let&#39;s go ahead and write those &lt;code&gt;toJSON()&lt;/code&gt; methods for our current model classes.  Since the model classes are &lt;em&gt;very&lt;/em&gt; simple, the methods will be trivial:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/6376ebd0dc2ca9b0d1cb48c77f09f3eb9878d5f3&#34;&gt;Commit 6376ebd: Add toJSON() methods for Redux-ORM model classes&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/6376ebd0dc2ca9b0d1cb48c77f09f3eb9878d5f3/src/features/pilots/Pilot.js&#34;&gt;features/pilots/Pilot.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;    static parse(mechData) {
        return this.create(mechData);
    }

+   toJSON() {
+       return {...this.ref};
+   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For now, all we&#39;re going to do is make a shallow copy of the actual plain JS object that&#39;s in the store.  Once our data starts using more complex relations, this would be the place to recurse through all of the 1:1 and 1:many relations, and call &lt;code&gt;toJSON()&lt;/code&gt; on them as well.  &lt;strong&gt;Since we don&#39;t have any classes like that right now, here&#39;s a quick example of what this might look like&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;class SomeHypotheticalModelWithRelations extends Model {
    toJSON() {}
        return {
            ...this.ref,
            someSingleRelation : this.someSingleRelation.toJSON(),
            someMultipleRelation : this.someMultipleRelation.withModels.map(item =&amp;gt; item.toJSON())
        };
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Nothing fancy - just translate the relational fields back into a nested plain JS object as appropriate.&lt;/p&gt;

&lt;p&gt;With all that in place, it&#39;s time to figure out what our editing reducer actually needs to do.&lt;/p&gt;

&lt;h3 id=&#34;writing-the-core-editing-reducer-logic&#34;&gt;Writing the Core Editing Reducer Logic&lt;/h3&gt;

&lt;p&gt;To start with, we need our editing reducer to handle three basic tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When we start editing an item, we need to copy it from the &amp;quot;current data&amp;quot; &lt;code&gt;entities&lt;/code&gt; slice to the &amp;quot;draft data&amp;quot; &lt;code&gt;editingEntities&lt;/code&gt; slice&lt;/li&gt;
&lt;li&gt;We need to be able to update the item in &lt;code&gt;editingEntities&lt;/code&gt; with new values&lt;/li&gt;
&lt;li&gt;When we&#39;re done editing the item, we need to delete the copy from &lt;code&gt;editingEntities&lt;/code&gt;, since it&#39;s not being used any more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We&#39;re going to define three initial actions for those tasks: &lt;code&gt;EDIT_ITEM_EXISTING&lt;/code&gt;, &lt;code&gt;EDIT_ITEM_UPDATE&lt;/code&gt;, and &lt;code&gt;EDIT_ITEM_STOP&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Remember that our editing reducer is a &amp;quot;top-level&amp;quot; reducer, and receives the &lt;em&gt;entire&lt;/em&gt; state tree as its &lt;code&gt;state&lt;/code&gt; argument.  That means it has access to both &lt;code&gt;state.entities&lt;/code&gt; and &lt;code&gt;state.editingEntities&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Looking back at our &amp;quot;generic entity CRUD&amp;quot; reducer, we can see that &lt;strong&gt;we already have individual case reducer functions that know how to create, update, and delete an entity in a slice of state&lt;/strong&gt;.  They&#39;re currently being used together to handle updates to the &lt;code&gt;state.entities&lt;/code&gt; slice as a whole, but &lt;strong&gt;we can import and reuse those individual case reducer functions as part of the editing reducer logic&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I&#39;ll link the commit that implements the reducers for these three cases, and explain each piece in turn:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/018c55214a03d25a8da8592390567dbd5878c411&#34;&gt;Commit 018c552: Add generic reducer logic for editing an entity&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/018c55214a03d25a8da8592390567dbd5878c411/src/features/editing/editingReducer.js&#34;&gt;features/editing/editingReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {createReducer} from &amp;quot;common/utils/reducerUtils&amp;quot;;

import {
    createEntity,
    updateEntity,
    deleteEntity
} from &amp;quot;features/entities/entityReducer&amp;quot;;

import {
    EDIT_ITEM_EXISTING,
    EDIT_ITEM_UPDATE,
    EDIT_ITEM_STOP
} from &amp;quot;./editingConstants&amp;quot;;

import {selectEntities} from &amp;quot;features/entities/entitySelectors&amp;quot;;
import {selectEditingEntities} from &amp;quot;./editingSelectors&amp;quot;;
import {
    readEntityData,
    updateEditingEntitiesState,
} from &amp;quot;./editingUtils&amp;quot;;

export function copyEntity(sourceEntities, destinationEntities, payload) {
    const {itemID, itemType} = payload;

    const newItemAttributes = readEntityData(sourceEntities, itemType, itemID);
    const creationPayload = {itemType, itemID, newItemAttributes}

    const updatedEntities = createEntity(destinationEntities, creationPayload);
    return updatedEntities;
}

export function editItemExisting(state, payload) {
    const entities = selectEntities(state);
    const editingEntities = selectEditingEntities(state);

    const updatedEditingEntities = copyEntity(entities, editingEntities, payload);
    return updateEditingEntitiesState(state, updatedEditingEntities);
}

export function editItemUpdate(state, payload) {
    const editingEntities = selectEditingEntities(state);

    const updatedEditingEntities = updateEntity(editingEntities, payload);
    return updateEditingEntitiesState(state, updatedEditingEntities);
}

export function editItemStop(state, payload) {
    const editingEntities = selectEditingEntities(state);

    const updatedEditingEntities = deleteEntity(editingEntities, payload);
    return updateEditingEntitiesState(state, updatedEditingEntities);
}

const editingFeatureReducer = createReducer({}, {
    [EDIT_ITEM_EXISTING] : editItemExisting,
    [EDIT_ITEM_UPDATE] : editItemUpdate,
    [EDIT_ITEM_STOP] : editItemStop,
});

export default editingFeatureReducer;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;First, &lt;code&gt;copyEntity()&lt;/code&gt; is an internal helper function, which isn&#39;t assigned to handle any specific cases.  It&#39;s called with two different state slices, one as a source and the other as a destination, and the payload from an action.  It uses the &lt;code&gt;readEntityData()&lt;/code&gt; utility method we wrote to look up a Model instance and copy its entire contents to a plain JS object.  Then, it uses the existing &lt;code&gt;createEntity()&lt;/code&gt; case reducer to parse that object and create a copy of the destination slice with the new item &amp;quot;inserted into the tables&amp;quot;.&lt;/p&gt;

&lt;p&gt;I want to pause and re-emphasize that idea: &lt;strong&gt;we&#39;re copying items by &amp;quot;serializing&amp;quot; the Models to plain objects, and then re-parsing them to create the duplicate Model instances&lt;/strong&gt;.  The &amp;quot;parsing&amp;quot; concept is the same function we&#39;re calling when we load the data from our fake API - we&#39;re reusing that here as our means of insertion.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;editItemExisting()&lt;/code&gt; case reducer is used to start the editing process for an item that already exists in the &amp;quot;current data&amp;quot; &lt;code&gt;state.entities&lt;/code&gt; slice.  We use small selectors to retrieve the &lt;code&gt;state.entities&lt;/code&gt; and &lt;code&gt;state.editingEntities&lt;/code&gt; slices, then pass them to &lt;code&gt;copyEntity()&lt;/code&gt;.  That returns us the newly updated &lt;code&gt;editingEntities&lt;/code&gt; slice, but we need to return that as part of the overall top-level state.  We use the &lt;code&gt;updateEditingEntitiesState()&lt;/code&gt; utility we wrote to do that.&lt;/p&gt;

&lt;p&gt;Similarly, the &lt;code&gt;editItemUpdate()&lt;/code&gt; case reducer reads the &lt;code&gt;editingEntities&lt;/code&gt; slice, passes that to the existing &lt;code&gt;updateEntity&lt;/code&gt; reducer, and returns the new top-level state with the updated &lt;code&gt;editingEntities&lt;/code&gt; slice.&lt;/p&gt;

&lt;p&gt;Finally, &lt;code&gt;editItemStop()&lt;/code&gt; deletes the item out of the &lt;code&gt;editingEntities&lt;/code&gt; slice, using the existing &lt;code&gt;deleteEntity()&lt;/code&gt; case reducer to do the work.&lt;/p&gt;

&lt;p&gt;Again, the idea here is that &lt;strong&gt;we already have a set of &amp;quot;primitive&amp;quot;, low-level reducer functions for manipulating entities in state, so we can reuse them as building blocks to create higher-level logic&lt;/strong&gt;.  Because hey, it&#39;s all just functions!&lt;/p&gt;

&lt;h2 id=&#34;using-draft-data-for-editing-pilots&#34;&gt;Using Draft Data for Editing Pilots&lt;/h2&gt;

&lt;p&gt;With those building blocks set, we can now begin updating our &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt; form to work with the new editing logic and data.&lt;/p&gt;

&lt;h3 id=&#34;displaying-the-copied-pilot-entry&#34;&gt;Displaying the Copied Pilot Entry&lt;/h3&gt;

&lt;p&gt;Since we&#39;re copying edited items from &lt;code&gt;entities&lt;/code&gt; to &lt;code&gt;editingEntities&lt;/code&gt;, our &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt; form will need to be able to switch which slice of state it&#39;s reading the pilot data from.  We&#39;ll add some additional logic to the &lt;code&gt;mapState&lt;/code&gt; function so that it can determine what slice it should use to load the data.  We also need to update the action creators to actually dispatch the &lt;code&gt;EDIT_ITEM_EXISTING&lt;/code&gt; and &lt;code&gt;EDIT_ITEM_STOP&lt;/code&gt; actions at the same time as we dispatch the &lt;code&gt;PILOT_EDIT_START&lt;/code&gt; and &lt;code&gt;PILOT_EDIT_STOP&lt;/code&gt; actions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/3cb01fc7da1242f068bd98fa3835070c213efecf&#34;&gt;Commit 3cb01fc: Add ability to display pilot entry from &amp;quot;draft&amp;quot; editingEntities slice&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/3cb01fc7da1242f068bd98fa3835070c213efecf/src/features/editing/editingSelectors.js&#34;&gt;features/editing/editingSelectors.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {createSelector} from &amp;quot;reselect&amp;quot;;

import schema from &amp;quot;app/schema&amp;quot;;

export const selectEditingEntities = state =&amp;gt; state.editingEntities;

export const getEditingEntitiesSession = createSelector(
    selectEditingEntities,
    editingEntities =&amp;gt; schema.from(editingEntities)
);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As with our &lt;code&gt;entities&lt;/code&gt; slice, we&#39;ll create a memoized selector that ensures we only have a single Redux-ORM Session instance per update to the &lt;code&gt;editingEntities&lt;/code&gt; slice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/3cb01fc7da1242f068bd98fa3835070c213efecf/src/features/pilots/pilotsActions.js&#34;&gt;features/pilots/pilotsActions.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;+import {
+   editExistingItem,
+   stopEditingItem
+} from &amp;quot;features/editing/editingActions&amp;quot;;


-export function startEditingPilot() {
-   return {
-       type : PILOT_EDIT_START,
-   };
-}
+export function startEditingPilot(pilotID) {
+   return (dispatch, getState) =&amp;gt; {
+       dispatch(editExistingItem(&amp;quot;Pilot&amp;quot;, pilotID));
+       dispatch({type : PILOT_EDIT_START});
+   }
+}

-export function stopEditingPilot() {
-   return {
-       type : PILOT_EDIT_STOP,
-   };
-}
+export function stopEditingPilot(pilotID) {
+   return (dispatch, getState) =&amp;gt; {
+       dispatch({type : PILOT_EDIT_STOP});
+       dispatch(stopEditingItem(&amp;quot;Pilot&amp;quot;, pilotID));
+   }
+}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We need to dispatch two different actions each time the &amp;quot;Start Editing&amp;quot; and &amp;quot;Stop Editing&amp;quot; buttons are clicked.  &lt;strong&gt;We&#39;ll change the existing plain action creators into thunks&lt;/strong&gt;, pass in the pilot IDs as arguments, and &lt;strong&gt;dispatch both the pilot-related action and the editing-related action in each thunk&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/3cb01fc7da1242f068bd98fa3835070c213efecf/src/features/pilots/PilotDetails/PilotDetails.jsx&#34;&gt;features/pilots/PilotDetails/PilotDetails.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {getEntitiesSession} from &amp;quot;features/entities/entitySelectors&amp;quot;;
+import {getEditingEntitiesSession} from &amp;quot;features/editing/editingSelectors&amp;quot;;

// Skip to mapState

    const currentPilot = selectCurrentPilot(state);

+   const pilotIsSelected = Boolean(currentPilot);
+   const isEditingPilot = selectIsEditingPilot(state);
+
+   if(pilotIsSelected) {
+       const session = isEditingPilot ?
+           getEditingEntitiesSession(state) :
+           getEntitiesSession(state);

        const {Pilot} = session;

        if(Pilot.hasId(currentPilot)) {
            pilot = Pilot.withId(currentPilot).ref;
        }
+    }

export class PilotDetails  extends Component {
+   onStartEditingClicked = () =&amp;gt; {
+       const {id} = this.props.pilot;
+       this.props.startEditingPilot(id);
+   }

+   onStopEditingClicked = () =&amp;gt; {
+       const {id} = this.props.pilot;
+       this.props.stopEditingPilot(id);
=   }

// Omit rendering code
                    &amp;lt;Button
                        primary
                        disabled={!canStartEditing}
                        type=&amp;quot;button&amp;quot;
-                       onClick={actions.startEditingPilot}                        
+                       onClick={this.onStartEditingClicked}
                    &amp;gt;
                        Start Editing
                    &amp;lt;/Button&amp;gt;
                    &amp;lt;Button
                        secondary
                        disabled={!canStopEditing}
                        type=&amp;quot;button&amp;quot;
-                       onClick={actions.stopEditingPilot}
+                       onClick={this.onStopEditingClicked}
                    &amp;gt;
                        Stop Editing
                    &amp;lt;/Button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We rework the &lt;code&gt;mapState&lt;/code&gt; function to determine whether we&#39;re currently editing a pilot or just displaying it.  Based on that, we retrieve either the editing Session or the &amp;quot;current data&amp;quot; Session, and read the Pilot out of there.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt; component gets a couple new click handlers, which extract the pilot ID from props, and call the appropriate action creator.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/3cb01fc7da1242f068bd98fa3835070c213efecf/src/features/editing/editingReducer.js&#34;&gt;features/editing/editingReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;    const newItemAttributes = readEntityData(sourceEntities, itemType, itemID);
+   if(newItemAttributes.name) {
+       newItemAttributes.name += &amp;quot; (copied)&amp;quot;;
+   }
    const creationPayload = {itemType, itemID, newItemAttributes}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As a visual indicator that we really are displaying the edited item, we&#39;ll temporarily modify our &lt;code&gt;copyEntity()&lt;/code&gt; function to append the text &amp;quot; (copied)&amp;quot; to the end of the name field.&lt;/p&gt;

&lt;p&gt;If we select a pilot and start editing it, we should now see:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-8/pilot-details-copied.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-8/pilot-details-copied.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;Progress!  We now have two different versions of the same pilot being displayed: the &amp;quot;current&amp;quot; entry in the list, and the &amp;quot;draft&amp;quot; entry in the form.&lt;/p&gt;

&lt;h3 id=&#34;updating-the-edited-entry&#34;&gt;Updating the Edited Entry&lt;/h3&gt;

&lt;p&gt;If you try typing in the &amp;quot;Name&amp;quot; field, you&#39;ll notice some very strange behavior.  As soon as you type anything, the list item for the pilot will update as well.  That&#39;s because we&#39;re still dispatching &lt;code&gt;ENTITY_UPDATE&lt;/code&gt;, instead of &lt;code&gt;EDIT_ITEM_UPDATE&lt;/code&gt;.  We need to modify &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt; to actually update the &amp;quot;draft&amp;quot; version.  While we&#39;re at it, we&#39;ll remove the little &amp;quot;(copied)&amp;quot; modification we made to the reducer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/d4660442479e02fde322d06b37c3662e584c1d9c&#34;&gt;Commit d466044: Update pilot editing logic to apply to draft entry&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/d4660442479e02fde322d06b37c3662e584c1d9c/src/features/pilots/PilotDetails/PilotDetails.jsx&#34;&gt;features/pilots/PilotDetails/PilotDetails.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;-import {updateEntity} from &amp;quot;features/entities/entityActions&amp;quot;;
+import {editItemAttributes} from &amp;quot;features/editing/editingActions&amp;quot;;

const actions = {
    startEditingPilot,
    stopEditingPilot,
-   updateEntity,
+   editItemAttributes,
}


   onInputChanged = (e) =&amp;gt; {
        const newValues = getValueFromEvent(e);
        const {id} = this.props.pilot;
        
-       this.props.updateEntity(&amp;quot;Pilot&amp;quot;, id, newValues);
+       this.props.editItemAttributes(&amp;quot;Pilot&amp;quot;, id, newValues);
    }

    onDropdownChanged = (e, result) =&amp;gt; {
        const {name, value} = result;
        const newValues = { [name] : value};
        const {id} = this.props.pilot;
        
-       this.props.updateEntity(&amp;quot;Pilot&amp;quot;, id, newValues);
+       this.props.editItemAttributes(&amp;quot;Pilot&amp;quot;, id, newValues);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, if you edit the pilot in the form, only that form should update.  The corresponding entry in the list should stay as it was.&lt;/p&gt;

&lt;h2 id=&#34;saving-form-edits&#34;&gt;Saving Form Edits&lt;/h2&gt;

&lt;p&gt;We can now edit a draft item, but when we click &amp;quot;Stop Editing&amp;quot;, the original item is still unchanged.  We need to overwrite the values in the original entry with the updated values in the draft entry.&lt;/p&gt;

&lt;h3 id=&#34;updating-existing-models&#34;&gt;Updating Existing Models&lt;/h3&gt;

&lt;p&gt;Earlier, we wrote a function called &lt;code&gt;copyEntity&lt;/code&gt;, which serializes the requested model (and its relations) to plain JS objects, and recreates them in the draft slice.  We now need to reverse the process, but this gets a bit tricker.  We already have an entry in the &lt;code&gt;entities&lt;/code&gt; slice, so we can&#39;t just call &lt;code&gt;createEntity()&lt;/code&gt; on that slice.  If we tried deleting it and immediately recreating it with the new values, Redux-ORM would also clear out all the relational fields that reference that same item, which would break things.  &lt;strong&gt;What we really need is a way to update the existing model &amp;quot;in-place&amp;quot;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is the other part that Tommi Kaikkonen helped me figure out.  &lt;strong&gt;We can write custom &lt;code&gt;updateFrom()&lt;/code&gt; methods on our Model classes, which take another model of the same type, and recursively update themselves and all their relations&lt;/strong&gt;.  It&#39;s basically the inverse operation of the sample &lt;code&gt;toJSON()&lt;/code&gt; function I showed earlier.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/df882199efee0fd65f0acb7569cdaa5142c6c2f0&#34;&gt;Commit df88219: Add updateFrom() methods to models&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/df882199efee0fd65f0acb7569cdaa5142c6c2f0/src/features/pilots/Pilot.js&#34;&gt;features/pilots/Pilot.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;    toJSON() {
        return {...this.ref};
    }

+   updateFrom(otherPilot) {
+       this.update(otherPilot.ref);
+   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Again, our current model classes don&#39;t have any complex relations, so the implementation is really simple.  We just call the built-in &lt;code&gt;update()&lt;/code&gt; method, and pass it the plain JS object that the other model wraps around (which, in our case, is stored in the other slice of state).&lt;/p&gt;

&lt;p&gt;(The process of updating a 1:many collection gets considerably more complicated, as you have to take into account adds, updates, and deletions.  In my real app, I wound up writing a reusable helper function to encapsulate the somewhat complex logic.  I plan to show that off later in the series, when we start dealing with more complex relations.)&lt;/p&gt;

&lt;h3 id=&#34;applying-changes-to-entities&#34;&gt;Applying Changes to Entities&lt;/h3&gt;

&lt;p&gt;We&#39;re going to write another core logic function that can load a model from a &amp;quot;source&amp;quot; slice, load its equivalent from the &amp;quot;destination&amp;quot; slice, and tell the destination entry to update itself with the source entry.  Then we&#39;ll write a case reducer that uses that function with &lt;code&gt;editingEntities&lt;/code&gt; as the source and &lt;code&gt;entities&lt;/code&gt; as the destination.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/4bd028d8584713b470120f302d16ab1ff14a42cc&#34;&gt;Commit 4bd028d: Add logic to apply item edits to the &amp;quot;current data&amp;quot; slice&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/4bd028d8584713b470120f302d16ab1ff14a42cc/src/features/editing/editingReducer.js&#34;&gt;features/editing/editingReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {createReducer} from &amp;quot;common/utils/reducerUtils&amp;quot;;

+import schema from &amp;quot;app/schema&amp;quot;;

import {
    EDIT_ITEM_EXISTING,
    EDIT_ITEM_UPDATE,
+   EDIT_ITEM_APPLY,
    EDIT_ITEM_STOP,
} from &amp;quot;./editingConstants&amp;quot;;

+import {getModelByType} from &amp;quot;common/utils/modelUtils&amp;quot;;

import {
    readEntityData,
+    updateEntitiesState,
    updateEditingEntitiesState,
} from &amp;quot;./editingUtils&amp;quot;;


+export function updateEditedEntity(sourceEntities, destinationEntities, payload) {
+   // Start by reading our &amp;quot;work-in-progress&amp;quot; data
+   const readSession = schema.from(sourceEntities);
+
+   const {itemType, itemID} = payload;
+
+   // Look up the model instance for the requested item
+   const model = getModelByType(readSession, itemType, itemID);
+
+   // We of course will be updating our &amp;quot;current&amp;quot; relational data
+   let writeSession = schema.from(destinationEntities);
+
+   const ModelClass = writeSession[itemType];
+
+   if(ModelClass.hasId(itemID)) {
+       // Look up the original Model instance for the top item
+       const existingItem = ModelClass.withId(itemID);
+
+       if(existingItem.updateFrom) {
+           // Each model class should know how to properly update itself and its
+           // relations from another model of the same type.  Ask the original model to
+           // update itself based on the &amp;quot;work-in-progress&amp;quot; model, which queues up a
+           // series of immutable add/update/delete actions internally
+           existingItem.updateFrom(model);
+       }
+   }
+
+   // Immutably apply the changes and generate our new &amp;quot;current&amp;quot; relational data
+   const updatedEntities = writeSession.reduce();
+   return updatedEntities;
+}
+
+

+export function editItemApply(state, payload) {
+   const entities = selectEntities(state);
+   const editingEntities = selectEditingEntities(state);

+   const updatedEntities = updateEditedEntity(editingEntities, entities, payload);
+   return updateEntitiesState(state, updatedEntities);
+}

const editingFeatureReducer = createReducer({}, {
    [EDIT_ITEM_EXISTING] : editItemExisting,
    [EDIT_ITEM_UPDATE] : editItemUpdate,
+   [EDIT_ITEM_APPLY] : editItemApply,
    [EDIT_ITEM_STOP] : editItemStop,
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The logic is fairly straightforward.  For &lt;code&gt;updateEditedEntity()&lt;/code&gt;, we create two separate Redux-ORM sessions, retrieve the models from each, call &lt;code&gt;existingItem.updateFrom(model)&lt;/code&gt;, and return the immutably updated state as normal.  The &lt;code&gt;editItemApply()&lt;/code&gt; case reducer just selects the two state slices, calls &lt;code&gt;updateEditedEntity()&lt;/code&gt;, and returns the updated root state.&lt;/p&gt;

&lt;h3 id=&#34;updating-pilot-save-logic&#34;&gt;Updating Pilot Save Logic&lt;/h3&gt;

&lt;p&gt;Our pilots reducer currently responds to the &lt;code&gt;PILOT_SELECT&lt;/code&gt; action by resetting &lt;code&gt;isEditing : false&lt;/code&gt;.  That was fine when we were just showing and editing the existing entry, but now we have some additional steps going on.  We really need to make sure that our editing data is cleaned up when another pilot is selected.&lt;/p&gt;

&lt;p&gt;We&#39;re going to update the &lt;code&gt;selectPilot()&lt;/code&gt; action creator to explicitly dispatch the &amp;quot;stop editing pilot&amp;quot; logic before it actually dispatches &lt;code&gt;PILOT_SELECT&lt;/code&gt;.  In the process, since we &lt;em&gt;know&lt;/em&gt; that you can only ever edit the current Pilot, we can rework the thunks to retrieve the current pilot from state instead of passing it in as a parameter.  (There&#39;s a very good discussion to be had about which approach is better, but we&#39;ll go ahead and make the changes for sake of illustrating the idea.)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/485104998e13fe58366d6a9539a883dd6e431566&#34;&gt;Commit 4851049: Rework pilot logic to explicitly stop editing on selection&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/485104998e13fe58366d6a9539a883dd6e431566/src/features/pilots/pilotsReducer.js&#34;&gt;features/pilots/pilotsReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;        currentPilot : isSamePilot ? null : newSelectedPilot,
-       // Any time we select a different pilot, we stop editing
-       isEditing : false,
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/485104998e13fe58366d6a9539a883dd6e431566/src/features/pilots/pilotsActions.js&#34;&gt;features/pilots/pilotsActions.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;+import {selectCurrentPilot, selectIsEditingPilot} from &amp;quot;./pilotsSelectors&amp;quot;;

export function selectPilot(pilotID) {
-   return {
-       type : PILOT_SELECT,
-       payload : {currentPilot : pilotID},
-   };
+   return (dispatch, getState) =&amp;gt; {
+       const state = getState();
+       const isEditing = selectIsEditingPilot(state);
+
+       if(isEditing) {
+           dispatch(stopEditingPilot())
+       }
+
+       dispatch({
+           type : PILOT_SELECT,
+           payload : {currentPilot : pilotID},
+       });
+   }
}

-export function startEditingPilot(pilotID) {
+export function startEditingPilot() {
    return (dispatch, getState) =&amp;gt; {
+       const currentPilot = selectCurrentPilot(getState());

-       dispatch(editExistingItem(&amp;quot;Pilot&amp;quot;, pilotID));
+       dispatch(editExistingItem(&amp;quot;Pilot&amp;quot;, currentPilot));
        dispatch({type : PILOT_EDIT_START});
    }
}

-export function stopEditingPilot(pilotID) {
+export function stopEditingPilot() {
    return (dispatch, getState) =&amp;gt; {
+       const currentPilot = selectCurrentPilot(getState());

        dispatch({type : PILOT_EDIT_STOP});
-       dispatch(stopEditingItem(&amp;quot;Pilot&amp;quot;, pilotID));
+       dispatch(stopEditingItem(&amp;quot;Pilot&amp;quot;, currentPilot));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;From there, we can simply add in the &amp;quot;apply edits&amp;quot; action as part of the &amp;quot;stop editing&amp;quot; thunk:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/f6608d0fdb9420e94d1d56e535c06902a9200645&#34;&gt;Commit f6608d0: Save changes to pilot entries when editing is stopped&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/f6608d0fdb9420e94d1d56e535c06902a9200645/src/features/pilots/pilotsActions.js&#34;&gt;features/pilots/pilotsActions.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {
    editExistingItem,
+   applyItemEdits,
    stopEditingItem
} from &amp;quot;features/editing/editingActions&amp;quot;;

export function stopEditingPilot() {
    return (dispatch, getState) =&amp;gt; {
        const currentPilot = selectCurrentPilot(getState());

        dispatch({type : PILOT_EDIT_STOP});
+       dispatch(applyItemEdits(&amp;quot;Pilot&amp;quot;, currentPilot));
        dispatch(stopEditingItem(&amp;quot;Pilot&amp;quot;, currentPilot));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And finally, &lt;strong&gt;whenever we hit the &amp;quot;Stop Editing&amp;quot; button, our changes are saved, and the list entry should be updated with whatever changes we made in the form&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&#34;resetting-and-canceling-form-edits&#34;&gt;Resetting and Canceling Form Edits&lt;/h2&gt;

&lt;p&gt;Our last couple tasks will be to add the ability to reset our form contents back to the original values, and to add the ability to cancel a form edit entirely.&lt;/p&gt;

&lt;h3 id=&#34;resetting-entity-edits&#34;&gt;Resetting Entity Edits&lt;/h3&gt;

&lt;p&gt;Happily, this is another feature we can implement very easily, by reusing existing code.  All we have to do is delete the relevant item out of the &lt;code&gt;editingEntities&lt;/code&gt; slice, and immediately copy the original item back over to &lt;code&gt;editingEntities&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/09c523602d07edee9c92034329d59c4662cbd0a3&#34;&gt;Commit 09c5236: Add logic to reset a currently edited item&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/09c523602d07edee9c92034329d59c4662cbd0a3/src/features/editing/editingReducer.js&#34;&gt;features/editing/editingReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {
    EDIT_ITEM_EXISTING,
    EDIT_ITEM_UPDATE,
    EDIT_ITEM_APPLY,
    EDIT_ITEM_STOP,
+   EDIT_ITEM_RESET,
} from &amp;quot;./editingConstants&amp;quot;;


+export function editItemReset(state, payload) {
+   const stateWithoutItem = editItemStop(state, payload);
+   const stateWithCurrentItem = editItemExisting(stateWithoutItem, payload);
+
+   return stateWithCurrentItem;
+}

const editingFeatureReducer = createReducer({}, {
    [EDIT_ITEM_EXISTING] : editItemExisting,
    [EDIT_ITEM_UPDATE] : editItemUpdate,
    [EDIT_ITEM_APPLY] : editItemApply,
    [EDIT_ITEM_STOP] : editItemStop,
+   [EDIT_ITEM_RESET] : editItemReset,
});
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;adding-reset-and-cancel-buttons&#34;&gt;Adding &amp;quot;Reset&amp;quot; and &amp;quot;Cancel&amp;quot; Buttons&lt;/h3&gt;

&lt;p&gt;The other neat thing is that we don&#39;t even need to create a &amp;quot;cancel&amp;quot; action.  We can do that by simply calling the same &amp;quot;stop editing&amp;quot; actions, and skip applying the item edits.&lt;/p&gt;

&lt;p&gt;We&#39;ll add a couple more buttons to our &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt; component, tweak the button layout a bit, and that&#39;ll be all:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/a4c2ce72f24841c90295f9d20c1252e0ad9eefab&#34;&gt;Commit a4c2ce7: Add the ability to reset and cancel editing a pilot&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/a4c2ce72f24841c90295f9d20c1252e0ad9eefab/src/features/pilots/pilotsActions.js&#34;&gt;features/pilots/pilotsActions.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;+export function cancelEditingPilot() {
+   return (dispatch, getState) =&amp;gt; {
+       const currentPilot = selectCurrentPilot(getState());
+
+       dispatch({type : PILOT_EDIT_STOP});
+       dispatch(stopEditingItem(&amp;quot;Pilot&amp;quot;, currentPilot));
+   }
+}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/a4c2ce72f24841c90295f9d20c1252e0ad9eefab/src/features/pilots/PilotDetails/PilotDetails.jsx&#34;&gt;features/pilots/PilotDetails/PilotDetails.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {
    startEditingPilot,
    stopEditingPilot,
+   cancelEditingPilot,
} from &amp;quot;../pilotsActions&amp;quot;;

+import {
+   resetEditedItem,
+} from &amp;quot;features/editing/editingActions&amp;quot;;


const actions = {
    startEditingPilot,
    stopEditingPilot,
    editItemAttributes,
+   resetEditedItem,
+   cancelEditingPilot,
}


export class PilotDetails  extends Component {

+   onResetClicked = () =&amp;gt; {
+       const {id} = this.props.pilot;
+       this.props.resetEditedItem(&amp;quot;Pilot&amp;quot;, id);
+   }

// Omit rendering code

+               &amp;lt;Grid.Row width={16}&amp;gt;
+                   &amp;lt;Button
+                       disabled={!canStopEditing}
+                       type=&amp;quot;button&amp;quot;
+                       onClick={this.onResetClicked}
+                   &amp;gt;
+                       Reset Values
+                   &amp;lt;/Button&amp;gt;
+                   &amp;lt;Button
+                       negative
+                       disabled={!canStopEditing}
+                       type=&amp;quot;button&amp;quot;
+                       onClick={this.props.cancelEditingPilot}
+                   &amp;gt;
+                       Cancel Edits
+                   &amp;lt;/Button&amp;gt;
+               &amp;lt;/Grid.Row&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can now start editing an item; save the item and stop editing; reset the draft item to its original values; and cancel an edit without actually saving the changes.  Yay!&lt;/p&gt;

&lt;p&gt;Let&#39;s take one last look at the current UI appearance:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-8/pilot-details-draft.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-8/pilot-details-draft.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;You can see that we&#39;re in the middle of editing a Pilot.  &lt;strong&gt;We&#39;ve edited several values, and they&#39;re different from what&#39;s being displayed in the list.  We also have our &amp;quot;Stop&amp;quot;, &amp;quot;Reset&amp;quot;, and &amp;quot;Cancel&amp;quot; buttons active, while &amp;quot;Start&amp;quot; is disabled.  Looks good!&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&#34;final-thoughts&#34;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;We&#39;ve come a long way from the start of the project&lt;/strong&gt;.  We&#39;ve built up a UI, added data loading, displayed our data, discussed performance concerns, and implemented some fairly sophisticated logic for handling normalized entities and working with forms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is a good place to pause the Practical Redux series for a while&lt;/strong&gt;.  I&#39;m absolutely &lt;em&gt;not&lt;/em&gt; done with the series, but I have a couple other blog posts that I want to write on other topics, and some non-blogging things I want to work on soon.  &lt;strong&gt;Rest assured, I have &lt;em&gt;many&lt;/em&gt; more topics that I want to cover in this series!&lt;/strong&gt;  (In fact, if you&#39;re interested in my writing plans, I have &lt;a href=&#34;https://gist.github.com/markerikson/840fc9baf9598971ae252b92ac832955&#34;&gt;a gist listing the blog post topics I want to write about in the future&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I&#39;d definitely like to thank everyone who has read these posts so far, and say how much I appreciate both the interest and the positive feedback you&#39;ve given me!&lt;/strong&gt;  It&#39;s extremely encouraging to know that people are actually interested in what I&#39;ve written, &lt;em&gt;and&lt;/em&gt; are finding the information helpful.&lt;/p&gt;

&lt;p&gt;Be sure to keep an eye on this blog for other posts coming soon, and I&#39;ll continue to tweet updates about what I&#39;m working on next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Until next time: keep on Redux-ing! :)&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&#34;further-information&#34;&gt;Further Information&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek&#34;&gt;Project Mini-Mek repo&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/8&#34;&gt;PR #8: Practical Redux Part 8 - WIP branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/9&#34;&gt;PR #9: Practical Redux Part 8 - Final branch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Selectors

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/reactjs/reselect&#34;&gt;Reselect repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/recipes/ComputingDerivedData.html&#34;&gt;Redux Docs: Computed Derived Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/react-redux-links/blob/master/redux-techniques.md#selectors-and-normalization&#34;&gt;React/Redux Links: Redux Techniques - Selectors and Normalization&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&amp;quot;Draft data&amp;quot; concept and discussion

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/recipes/reducers/NormalizingStateShape.html&#34;&gt;Redux Docs: Structuring Reducers - Normalizing State Shape&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/tommikaikkonen/redux-orm/issues/22&#34;&gt;Redux-ORM #22: Best way to implement updates from cloned data?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://stackoverflow.com/questions/40253864/strategy-for-data-management-in-react&#34;&gt;Stack Overflow - &amp;quot;Strategy for data management in React?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/cjke/react-example-1-redux-orm&#34;&gt;Redux-ORM draft view example repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Reducers

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/recipes/StructuringReducers.html&#34;&gt;Redux Docs: Structuring Reducers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/react-redux-links/blob/master/redux-techniques.md#reducers&#34;&gt;React/Redux Links: Redux Techniques - Reducers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gist.github.com/markerikson/840fc9baf9598971ae252b92ac832955&#34;&gt;Mark&#39;s blog post todo list&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    
    <item>
      <title>Practical Redux, Part 7: Form Change Handling, Data Editing, and Feature Reducers</title>
      <link>https://blog.isquaredsoftware.com/2017/01/practical-redux-part-7-forms-editing-reducers/</link>
      <pubDate>Thu, 12 Jan 2017 23:00:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2017/01/practical-redux-part-7-forms-editing-reducers/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/2017/01/practical-redux-part-6-connected-lists-forms-and-performance/&#34;&gt;In Part 6&lt;/a&gt;&lt;/strong&gt;, we connected our lists directly to Redux, set up basic editing for the UnitInfo form, and added the ability to toggle &amp;quot;editing&amp;quot; mode for a selected Pilot.  This time, we&#39;ll &lt;strong&gt;look at some advanced techniques for managing form change events, implement editing for model entries, and use a custom reducer structure to handle feature logic&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The code for this project is on Github at &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek&#34;&gt;github.com/markerikson/project-minimek&lt;/a&gt;&lt;/strong&gt;.  Since this post was split off from Part 6, the original WIP commits I made for this post can be seen in &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/6&#34;&gt;PR #6: Practical Redux Part 6 WIP&lt;/a&gt;&lt;/strong&gt;, and the final &amp;quot;clean&amp;quot; commits can be seen in in &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/7&#34;&gt;PR #7: Practical Redux Part 7 Final&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I&#39;ll be linking to each &amp;quot;final&amp;quot; commit as I go through the post, as well as specific files in those commits.  I won&#39;t paste every changed file in here or show every single changed line, to save space, but rather try to show the most relevant changes for each commit as appropriate.&lt;/p&gt;

&lt;h3 id=&#34;table-of-contents&#34;&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#cleaning-up-some-code&#34;&gt;Cleaning Up Some Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#investigating-form-actions&#34;&gt;Investigating Form Actions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#buffering-form-changes-and-dispatches&#34;&gt;Buffering Form Changes and Dispatches&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#structuring-reducer-logic-for-features&#34;&gt;Structuring Reducer Logic for Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#editing-pilot-entries&#34;&gt;Editing Pilot Entries&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#final-thoughts&#34;&gt;Final Thoughts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#further-information&#34;&gt;Further Information&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;cleaning-up-some-code&#34;&gt;Cleaning Up Some Code&lt;/h2&gt;

&lt;p&gt;Before we dive in to the real work for this section, we&#39;ve got a few bits of cleanup that will help us later.&lt;/p&gt;

&lt;h3 id=&#34;handling-data-reloads&#34;&gt;Handling Data Reloads&lt;/h3&gt;

&lt;p&gt;There&#39;s a problem with the current &lt;code&gt;entitiesReducer&lt;/code&gt; logic.  If we click the &amp;quot;Load Unit Info&amp;quot; button twice in a session, the reducer will try to load the same sample data again, and will throw errors because data with those IDs already exists in state.  We can fix this by having the case reducer delete any existing entries before it loads in the new data.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/36324ea46ae1f0fcda44816c3820c255a82aa5a8&#34;&gt;Commit 36324ea: Clear out existing models on load to avoid conflicts when reloading data&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/36324ea46ae1f0fcda44816c3820c255a82aa5a8/src/app/reducers/entitiesReducer.js&#34;&gt;app/reducers/entitiesReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;    const {pilots, designs, mechs} = payload;

+   // Clear out any existing models from state so that we can avoid
+   // conflicts from the new data coming in if data is reloaded
+   [Pilot, Mech, MechDesign].forEach(modelType =&amp;gt; {
+       modelType.all().withModels.forEach(model =&amp;gt; model.delete());
+       session.state = session.reduce();
+   });
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that we use the &lt;code&gt;session.state = session.reduce()&lt;/code&gt; trick mentioned in &lt;a href=&#34;https://blog.isquaredsoftware.com/2016/10/practical-redux-part-2-redux-orm-concepts-and-techniques/&#34;&gt;Part 2&lt;/a&gt; to create an intermediate updated version of the state after queueing up the delete commands for each model class.&lt;/p&gt;

&lt;h3 id=&#34;cleaning-up-the-pilotdetails-component&#34;&gt;Cleaning Up the PilotDetails Component&lt;/h3&gt;

&lt;p&gt;Since we&#39;re going to eventually add callback functions to handle the inputs in &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt;, now is a good time to convert it from a functional component to a class component.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/e1325aceead25a847476374f77a0467c9e15e25b&#34;&gt;Commit e1325ac: Convert PilotDetails to a class component&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We&#39;re also going to rework the &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt; form a bit.  The &amp;quot;gunnery&amp;quot; and &amp;quot;piloting&amp;quot; fields are going to have a limited range of values, so we might as well make them dropdowns.  Also, while working on this part, I found out that the Semantic-UI-React &lt;code&gt;&amp;lt;Form.Field&amp;gt;&lt;/code&gt; component supports some useful shorthand syntax.  You can pass a label string and a component type as a prop, and it will render them.  It will also forward any unknown props onwards to the input component it&#39;s rendering.  here&#39;s an example:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;-&amp;lt;Form.Field name=&amp;quot;rank&amp;quot; width={16}&amp;gt;
-   &amp;lt;label&amp;gt;Rank&amp;lt;/label&amp;gt;
-   &amp;lt;Dropdown
-       fluid
-       selection
-       options={RANKS}
-       value={rank}
-       disabled={!canStopEditing}
-   /&amp;gt;
-&amp;lt;/Form.Field&amp;gt;
+&amp;lt;Form.Field
+   name=&amp;quot;rank&amp;quot;
+   label=&amp;quot;Rank&amp;quot;
+   width={16}
+   control={Dropdown}
+   fluid
+   selection
+   options={RANKS}
+   value={rank}
+   disabled={!canStopEditing}
+/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;label&lt;/code&gt;, and &lt;code&gt;width&lt;/code&gt; props are handled by the &lt;code&gt;&amp;lt;Form.Field&amp;gt;&lt;/code&gt; component.  It renders an instance of &lt;code&gt;&amp;lt;Dropdown&amp;gt;&lt;/code&gt;, and passes it the remaining props.  (Order doesn&#39;t matter here, I just wrote them with the Field&#39;s props first and the Dropdown&#39;s props last.)&lt;/p&gt;

&lt;p&gt;I suppose it&#39;s a tossup which formatting you prefer.  I can see arguments both ways.  But, given that I already did the work, we&#39;ll go with the latter approach :)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/dcdc0ec2dbb5dee0c4c6bec459eaa3d5818033c9&#34;&gt;Commit dcdc0ec: Rework PilotDetails form layout for consistency&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;investigating-form-actions&#34;&gt;Investigating Form Actions&lt;/h2&gt;

&lt;p&gt;With that cleanup done, back to work on our input forms.  In &lt;a href=&#34;https://blog.isquaredsoftware.com/2017/01/practical-redux-part-6-connected-lists-forms-and-performance/&#34;&gt;Part 6&lt;/a&gt;, I mentioned that &lt;strong&gt;&amp;quot;there&#39;s one problem with our text input that we need to address&amp;quot;&lt;/strong&gt;, and promised we&#39;d come back to that later.  Later is now :)&lt;/p&gt;

&lt;p&gt;Let&#39;s type the letters &amp;quot;test&amp;quot; into the end of the &amp;quot;Unit Name&amp;quot; field, and look at the DevTools actions log:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-7/unit-name-actions.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-7/unit-name-actions.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;We can see four different &lt;code&gt;UNIT_INFO_UPDATE&lt;/code&gt; actions in that list from typing &amp;quot;test&amp;quot; into the name input.  If we look at the next-to-last action, we can see that after typing the &#39;s&#39;, the dispatched name was &amp;quot;Black Widow Companytes&amp;quot;.&lt;/p&gt;

&lt;p&gt;Right now, &lt;strong&gt;every single time we type a keystroke into the name input, we dispatch another Redux action&lt;/strong&gt;.  Every time we dispatch an action, &lt;em&gt;every&lt;/em&gt; connected component gets notified, and has its &lt;code&gt;mapState&lt;/code&gt; function run.  As an example, that means that for every keystroke, all the &lt;code&gt;&amp;lt;PilotsListRow&amp;gt;&lt;/code&gt; components are busy looking up their Pilot entries.  But... all we really wanted to do was update the name input!  None of the Pilots data is going to change from us typing here, so all that is wasted effort.  The dispatched actions are also kind of cluttering up the actions log.&lt;/p&gt;

&lt;p&gt;As mentioned previously, &lt;strong&gt;&lt;em&gt;Project Mini-Mek&lt;/em&gt;&lt;/strong&gt; really isn&#39;t a performance-critical application, and especially not at this stage of development.  Still, &lt;strong&gt;it would be nice if we could cut down on the number of actual Redux actions dispatched&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&#34;buffering-form-changes-and-dispatches&#34;&gt;Buffering Form Changes and Dispatches&lt;/h2&gt;

&lt;p&gt;I noted some of the issues with dispatching actions from form inputs while working on early prototypes for my own application.  I needed a solution that could do several things for me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handle &lt;code&gt;onChange&lt;/code&gt; events from input components&lt;/li&gt;
&lt;li&gt;Respond to those change events by immediately passing the updated values back down to the input, for fast UI response&lt;/li&gt;
&lt;li&gt;If several changes happened close together, only dispatch a single Redux action after they were all done, with the final values&lt;/li&gt;
&lt;li&gt;Be generic enough that I could reuse it in a variety of different places.&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I started playing around with some ideas, and eventually came up with a component I dubbed the &amp;quot;FormEditWrapper&amp;quot;.  (As you may have noticed, nothing is more permanent in programming than a temporary name.  We&#39;ll call it &lt;code&gt;FEW&lt;/code&gt; for short.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My &lt;code&gt;FormEditWrapper&lt;/code&gt; is a reusable, generic component that can buffer input changes in its own component state, combine those changes with incoming props, and debounce changes to minimize the number of dispatched Redux actions.&lt;/strong&gt;.  Let&#39;s look at the source, and I&#39;ll explain how it works.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/c321c35e7766705eb11517696ad11f385181bae2&#34;&gt;Commit c321c35: Add FormEditWrapper component&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/c321c35e7766705eb11517696ad11f385181bae2/src/common/components/FormEditWrapper.jsx&#34;&gt;common/components/FormEditWrapper.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import React, {Component, PropTypes} from &amp;quot;react&amp;quot;;
import {noop, debounce, defaults, values} from &amp;quot;lodash&amp;quot;;

import {getValueFromEvent} from &amp;quot;common/utils/clientUtils&amp;quot;;

class FormEditWrapper extends Component {
    static propTypes = {
        value : PropTypes.object.isRequired,
        isEditing : PropTypes.bool,
        onChange : PropTypes.func,
        valuePropName : PropTypes.string,
        onChangePropName : PropTypes.string,
        singleValue : PropTypes.bool,
        passIsEditing : PropTypes.bool,
        dispatchDelay : PropTypes.number,
    }
    
    static defaultProps = {
        isEditing : true,
        onChange : noop,
        valuePropName : &amp;quot;value&amp;quot;,
        onChangePropName : &amp;quot;onChange&amp;quot;,
        singleValue : false,
        passIsEditing : true,
        dispatchDelay : 250,
    }

    constructor(props) {
        super(props);
        const boundDispatchAttributes = this.dispatchAttributeChange.bind(this);
        this.dispatchAttributeChange = debounce(boundDispatchAttributes, props.dispatchDelay);

        this.state = {
            value : {},
        };
    }

    componentWillReceiveProps() {
        // Reset any component-local changes  Note that the incoming props
        // SHOULD match the changes we just had in local state.
        this.setState({value : {}});
    }

    onChildChange = (e) =&amp;gt; {
        const {isEditing} = this.props;

        if(isEditing) {
            const newValues = getValueFromEvent(e);

            if(newValues) {
                const change = {
                    ...this.state.value,
                    ...newValues
                };

                // Update our component-local state with these changes, so that the child components
                // will re-render with the new values right away
                this.setState({value : change});

                // Because this is debounced, we will only call the passed-in props.onChange
                // once there is a pause in changes (like letting go of a held-down key)
                this.dispatchAttributeChange(change);
            }
        }
    }

    dispatchAttributeChange(change) {
        this.props.onChange(change);
    }

    render() {
        const {value : propsValue, children} = this.props;
        const {isEditing, passIsEditing, valuePropName, onChangePropName, singleValue} = this.props;
        const {value : stateValue = {}} = this.state;

        // Use incoming values from props IF there is no corresponding value
        // in local component state.  This allows local changes to win out.
        const currentValues = defaults({}, stateValue, propsValue);

        let valueToPassDown = currentValues;

        if(singleValue) {
            valueToPassDown = values(currentValues)[0];
        }

        const editingValue = passIsEditing ? {isEditing} : {};

        // Force the child form to re-render itself with these values
        const child = React.Children.only(children);

        const updatedChild = React.cloneElement(child, {
            [valuePropName] : valueToPassDown,
            [onChangePropName] : this.onChildChange,
            ...editingValue
        });

        return updatedChild;
    }
}

export default FormEditWrapper;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There&#39;s a lot of stuff going on in there.  Let&#39;s break it down:&lt;/p&gt;

&lt;h3 id=&#34;passing-down-props-to-children&#34;&gt;Passing Down Props to Children&lt;/h3&gt;

&lt;p&gt;First, &lt;code&gt;FEW&lt;/code&gt; expects a prop named &lt;code&gt;value&lt;/code&gt;, which should be an object.  It also uses the &lt;code&gt;React.Children&lt;/code&gt; API to ensure that it only has a single child.  The most basic usage would look like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;&amp;lt;FormEditWrapper value={someObject}&amp;gt;
    &amp;lt;SomeChildComponent /&amp;gt;
&amp;lt;/FormEditWrapper&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;FEW&lt;/code&gt; also uses another of React&#39;s top-level APIs: &lt;code&gt;React.cloneElement()&lt;/code&gt;.  Since the output of a React render function is just an object, and React exposes the render output of child components as &lt;code&gt;props.children&lt;/code&gt;, &lt;strong&gt;it&#39;s possible for a component to return different children than what it was given&lt;/strong&gt;.  In this case, &lt;code&gt;FEW&lt;/code&gt; is going to make a copy of the child render output it was given, and pass down a couple new or different props.  One prop is the data value object, and the other prop is an &lt;code&gt;onChange&lt;/code&gt; callback.  So, in that minimal example, it&#39;s as if we had written &lt;code&gt;SomeChildComponent value={someObject} onChange={someOnChangeCallback} /&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The second thing to note is that &lt;code&gt;FEW&lt;/code&gt; supplies its own &lt;code&gt;onChildChanged&lt;/code&gt; method as the &lt;code&gt;onChange&lt;/code&gt; prop for its child.  Whenever &lt;code&gt;onChildChanged&lt;/code&gt; is called, &lt;code&gt;FEW&lt;/code&gt; will update its internal state with the values passed up by the child, merging them with whatever values are already buffered in the state.  Calling &lt;code&gt;this.setState()&lt;/code&gt; always forces a re-render, and that leads into the next really interesting part.&lt;/p&gt;

&lt;p&gt;Let&#39;s use the &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt; form as an example.  That form has two main text inputs (name and age).  Assume we have this setup:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;const name = &amp;quot;Original Name&amp;quot;;
const age = &amp;quot;42&amp;quot;;

&amp;lt;FormEditWrapper value={ {name, age} }&amp;gt;
    &amp;lt;PilotDetails /&amp;gt;
&amp;lt;/FormEditWrapper&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we type &amp;quot;newname&amp;quot; at the end of the &lt;code&gt;name&lt;/code&gt; field, &lt;code&gt;FEW&lt;/code&gt;&#39;s internal state would look like &lt;code&gt;{ value : { name : &amp;quot;Original Namenewname&amp;quot;}}&lt;/code&gt;.  Meanwhile it&#39;s still being given the original &lt;code&gt;value={ {name, age} }&lt;/code&gt; prop.  We need to combine these two so that the name value we just typed overrides the name value coming in as a prop.  The key is this line here:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;// Use incoming values from props IF there is no corresponding value
// in local component state.  This allows local changes to win out.
const currentValues = defaults({}, stateValue, propsValue);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we were to inspect &lt;code&gt;currentValues&lt;/code&gt; after that line, we would see &lt;code&gt;{name : &amp;quot;Original Namenewname&amp;quot;, age : 42}&lt;/code&gt;.  Since we didn&#39;t have an &lt;code&gt;age&lt;/code&gt; prop in &lt;code&gt;FEW&lt;/code&gt;&#39;s state, we copy that over.  Since we &lt;em&gt;do&lt;/em&gt; have a &lt;code&gt;name&lt;/code&gt; field in state, we &lt;em&gt;don&#39;t&lt;/em&gt; copy over the &lt;code&gt;name&lt;/code&gt; field we were given as a prop.  This means that any values from the child component will override the equivalent values from props, and the resulting object is passed back down to the child component, allowing it to re-render itself with the correct data.&lt;/p&gt;

&lt;p&gt;Finally, when &lt;code&gt;FEW&lt;/code&gt; receives new props, it clears out its internal state buffer.  The assumption is that the new props will now be a &amp;quot;saved&amp;quot; version of the changes it&#39;s keeping inside, so it can clear those out and go back to just passing down the data it&#39;s getting as a prop.&lt;/p&gt;

&lt;h3 id=&#34;flexibility-and-customization&#34;&gt;Flexibility and Customization&lt;/h3&gt;

&lt;p&gt;Perhaps the child input or form component is different than most others.  Maybe it needs its value as a prop named &lt;code&gt;data&lt;/code&gt; (or in the case of &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt;, as a prop named &lt;code&gt;pilot&lt;/code&gt;).  Maybe it needs the callback prop to be named something other than &lt;code&gt;onChange&lt;/code&gt;.  &lt;code&gt;FEW&lt;/code&gt; accepts some props that tell it to change its default behavior: &lt;code&gt;valuePropName&lt;/code&gt; and &lt;code&gt;onChangePropName&lt;/code&gt;.  Going back to our earlier example, we could do:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;&amp;lt;FormEditWrapper value={ {name, age} }  valuePropName=&amp;quot;pilot&amp;quot;&amp;gt;
    &amp;lt;PilotDetails /&amp;gt;
&amp;lt;/FormEditWrapper&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt; will be given &lt;code&gt;props.pilot&lt;/code&gt; instead of &lt;code&gt;props.value&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Another customization issue is that actual &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; components only want a specific value like a string, instead of an object.  In that case, passing the &lt;code&gt;singleValue={true}&lt;/code&gt; flag to &lt;code&gt;FEW&lt;/code&gt; will tell it to assume there&#39;s only one field it needs to pass down, and to pass that down directly instead of the entire value object.&lt;/p&gt;

&lt;p&gt;In my own application, a number of components also need to be given an &lt;code&gt;isEditing&lt;/code&gt; flag.  Originally I passed that through all the time, but when I added the &lt;code&gt;singleValue&lt;/code&gt; option, I realized that inputs wouldn&#39;t need that prop, so I added a &lt;code&gt;passIsEditing&lt;/code&gt; prop to control whether that gets passed down or not.&lt;/p&gt;

&lt;h3 id=&#34;buffering-dispatches&#34;&gt;Buffering Dispatches&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;FEW&lt;/code&gt;&#39;s &lt;code&gt;onChildChanged&lt;/code&gt; method will immediately call &lt;code&gt;this.setState()&lt;/code&gt; with the new values from the child, and that queues up a re-render.  That method also calls &lt;code&gt;this.dispatchAttributeChanged()&lt;/code&gt;, which in turn calls &lt;code&gt;this.props.onChange()&lt;/code&gt;.  However, in the constructor, we create a debounced version of &lt;code&gt;dispatchAttributeChanged&lt;/code&gt;, which will only actually run if enough time has elapsed since the last time it was called (by default, 250ms).  That means that if the user quickly types several characters into a text input, &lt;code&gt;dispatchAttributeChanged&lt;/code&gt; will be called repeatedly, but won&#39;t actually run for real until after the user is done typing.  As a result, when it &lt;em&gt;does&lt;/em&gt; run, it will call &lt;code&gt;this.props.onChange()&lt;/code&gt; with the final value.  So, instead of seeing &lt;code&gt;&amp;quot;n&amp;quot;&lt;/code&gt;, &lt;code&gt;&amp;quot;ne&amp;quot;&lt;/code&gt;, &lt;code&gt;&amp;quot;new&lt;/code&gt;&amp;quot;, and so on, you&#39;d see a single &lt;code&gt;&amp;quot;newname&amp;quot;&lt;/code&gt; value passed back up.  The &lt;code&gt;onChange&lt;/code&gt; prop doesn&#39;t have to be a Redux action creator, but it usually will be.  That means that &lt;strong&gt;most of the time, only a single Redux action will be dispatched for a series of keystrokes&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&#34;formeditwrapper-in-action&#34;&gt;&lt;code&gt;FormEditWrapper&lt;/code&gt; in Action&lt;/h3&gt;

&lt;p&gt;With all that in mind, let&#39;s use &lt;code&gt;FEW&lt;/code&gt; to buffer the &amp;quot;name&amp;quot; input in our &lt;code&gt;&amp;lt;UnitInfo&amp;gt;&lt;/code&gt; component.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/76e48af2aa77f6224d81e8bb29cb5631c0848de5&#34;&gt;Commit 76e48af: Use FormEditWrapper with UnitInfo name input&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/76e48af2aa77f6224d81e8bb29cb5631c0848de5/src/features/unitInfo/UnitInfo/UnitInfo.jsx&#34;&gt;features/unitInfo/UnitInfo/UnitInfo.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;+import FormEditWrapper from &amp;quot;common/components/FormEditWrapper&amp;quot;;

// Omit irrelevant code
    render() {
-       const {unitInfo} = this.props;
+       const {unitInfo, updateUnitInfo} = this.props;
        const {name, affiliation} = unitInfo;

// Omit rendering code
                    &amp;lt;Form.Field name=&amp;quot;name&amp;quot; width={6}&amp;gt;
                        &amp;lt;label&amp;gt;Unit Name&amp;lt;/label&amp;gt;
+                       &amp;lt;FormEditWrapper
+                           singleValue={true}
+                           value={ {name} }
+                           onChange={updateUnitInfo}
+                           passIsEditing={false}
+                       &amp;gt;
                            &amp;lt;input
                                placeholder=&amp;quot;Name&amp;quot;
                                name=&amp;quot;name&amp;quot;
-                           value={name}
-                           onChange={this.onNameChanged}
                            /&amp;gt;
+                       &amp;lt;/FormEditWrapper&amp;gt;
                    &amp;lt;Form.Field name=&amp;quot;affiliation&amp;quot; width={6}&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So now, if we type &amp;quot;test&amp;quot; at the end of the name input and look in the DevTools, we should see this:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-7/unit-name-actions-buffered.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-7/unit-name-actions-buffered.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;&lt;strong&gt;Success!  Four keystrokes, the input updated immediately as we typed, and only a single Redux action was dispatched.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&#34;structuring-reducer-logic-for-features&#34;&gt;Structuring Reducer Logic for Features&lt;/h2&gt;

&lt;p&gt;As mentioned in &lt;a href=&#34;https://blog.isquaredsoftware.com/2016/11/practical-redux-part-4-ui-layout-and-project-structure/&#34;&gt;Part 4&lt;/a&gt;, we&#39;re using a &amp;quot;feature-first&amp;quot; folder structure.  There&#39;s tradeoffs with both &amp;quot;file-type-first&amp;quot; and &amp;quot;feature-first&amp;quot; approaches.&lt;/p&gt;

&lt;p&gt;With &amp;quot;file-type-first&amp;quot;, you know where to look for a certain type of code, and it&#39;s really easy to pull together all the slice reducers into a root reducer file.  However, each feature gets split across several folders, and if multiple features need to interact with a specific slice of state, the files or folders for that slice of reducer logic will start to get awfully crowded.&lt;/p&gt;

&lt;p&gt;With &amp;quot;feature-first&amp;quot;, you know exactly where &lt;em&gt;all&lt;/em&gt; the files for a given feature are, but the process of combining the reducer logic together can be a bit tricker, especially if you&#39;re using the standard approach of &lt;code&gt;combineReducers&lt;/code&gt;.  In particular, &lt;strong&gt;what happens when multiple features need to interact with the same slice of state?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In our case, we&#39;ve created an &lt;code&gt;entities&lt;/code&gt; slice containing the &amp;quot;tables&amp;quot; for our relational data entries.  Because this is a central data location for our application, several different features are going to need to make updates to the &lt;code&gt;entities&lt;/code&gt; slice.  We &lt;em&gt;could&lt;/em&gt; put all the reducer logic from the different features together into one giant &lt;code&gt;entitiesReducer&lt;/code&gt;, but that would get ugly rather quickly.  &lt;strong&gt;What we really need is a way for each individual feature to separately apply updates to the &lt;code&gt;entities&lt;/code&gt; slice.&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&#34;looking-beyond-combinereducers&#34;&gt;Looking Beyond &lt;code&gt;combineReducers&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;I&#39;ll paraphrase some of the key concepts from the &lt;strong&gt;&lt;a href=&#34;http://redux.js.org/docs/recipes/StructuringReducers.html&#34;&gt;Structuring Reducers&lt;/a&gt;&lt;/strong&gt; section of the Redux docs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It&#39;s important to understand that your entire application really only has &lt;strong&gt;one single reducer function&lt;/strong&gt;: the function that you&#39;ve passed into &lt;code&gt;createStore&lt;/code&gt; as the first argument.  It&#39;s good programming practice to take pieces of code that are very long or do many different things, and break them into smaller pieces that are easier to understand.  Since a Redux reducer is just a function, the same concept applies. &lt;strong&gt;You can split some of your reducer logic out into another function, and call that new function from the parent function&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In Redux it is very common to structure reducer logic by delegating to other functions based on slice of state. Redux refers to this concept as &amp;quot;reducer composition&amp;quot;, and it is by far the most widely-used approach to structuring reducer logic. In fact, it&#39;s so common that Redux includes a utility function called &lt;code&gt;combineReducers()&lt;/code&gt;, which specifically abstracts the process of delegating work to other reducer functions based on slices of state. However, &lt;strong&gt;it&#39;s important to note that it is not the only pattern that can be used&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Once you go past the core use case for &lt;code&gt;combineReducers&lt;/code&gt;, &lt;strong&gt;it&#39;s time to use more &amp;quot;custom&amp;quot; reducer logic&lt;/strong&gt;, whether it be specific logic for a one-off use case, or a reusable function that could be widely shared.  There&#39;s third-party reducer utilities that are available, or if none of the published utilities solve your use case, &lt;strong&gt;you can always write a function yourself that does just exactly what you need&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It&#39;s time to put some of these ideas into practice.&lt;/p&gt;

&lt;h3 id=&#34;using-reducereducers&#34;&gt;Using &lt;code&gt;reduceReducers&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;If you happened to look at the &lt;code&gt;reducerUtils.js&lt;/code&gt; file previously, you may have noted a function in there I haven&#39;t talked about yet: &lt;code&gt;reduceReducers()&lt;/code&gt;.  Here it is:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;export function reduceReducers(...reducers) {
    return (previous, current) =&amp;gt;
        reducers.reduce(
            (p, r) =&amp;gt; r(p, current),
            previous
        );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This was actually originally written by Andrew Clark, and is available as a package at &lt;a href=&#34;https://github.com/acdlite/reduce-reducers&#34;&gt;https://github.com/acdlite/reduce-reducers&lt;/a&gt; .  I swiped it and pasted it into &lt;code&gt;reducerUtils.js&lt;/code&gt; to skip taking on another dependency.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;reduceReducers&lt;/code&gt; is a nifty little utility.  It lets us supply multiple reducer functions as arguments and effectively forms a pipeline out of those functions, then returns a new reducer function.  If we call that new reducer with the top-level state, it will call the first input reducer with the state, pass the output of that to the second input reducer, and so on.  (If I were more Functional-Programming-minded, I&#39;d guess that there&#39;s probably a lot of similarities with &lt;code&gt;compose()&lt;/code&gt;, but this is about as far as my mind goes in that direction.  I&#39;m sure someone will be happy to correct me or clarify things in the comments.)&lt;/p&gt;

&lt;p&gt;Let&#39;s rework our root reducer to make use of &lt;code&gt;reduceReducers&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/9d6b44313b7f2f2a5c2690939d942e3ce5b7cfc6&#34;&gt;Commit 9d6b443: Update root reducer to wrap around combined reducer&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/9d6b44313b7f2f2a5c2690939d942e3ce5b7cfc6/src/app/reducers/rootReducer.js&#34;&gt;app/reducers/rootReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {reduceReducers} from &amp;quot;common/utils/reducerUtils&amp;quot;;

const combinedReducer = combineReducers({
    entities : entitiesReducer,
    unitInfo : unitInfoReducer,
    pilots : pilotsReducer,
    mechs : mechsReducer,
    tabs : tabReducer,
});


const rootReducer = reduceReducers(
    combinedReducer,
);

export default rootReducer;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Our old &amp;quot;root reducer&amp;quot; is now the &lt;code&gt;combinedReducer&lt;/code&gt;, and we pass that into &lt;code&gt;reduceReducers&lt;/code&gt; to get the new root reducer.&lt;/p&gt;

&lt;p&gt;It&#39;s important to note that &lt;strong&gt;the combined reducer should be first in the pipeline, because that defines the shape of the state&lt;/strong&gt;.  (See the &lt;a href=&#34;http://redux.js.org/docs/recipes/reducers/InitializingState.html&#34;&gt;Initializing State&lt;/a&gt; section of the Redux docs for more info on why and how the combined reducer defines the state shape.)&lt;/p&gt;

&lt;h3 id=&#34;writing-a-higher-order-reducer&#34;&gt;Writing a Higher Order Reducer&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A &amp;quot;higher order reducer&amp;quot; is any function that takes a reducer as an argument, and returns a new reducer&lt;/strong&gt;.  That includes &lt;code&gt;combineReducers&lt;/code&gt; and &lt;code&gt;reduceReducers&lt;/code&gt;.  Now, we&#39;re going to write one of our own.&lt;/p&gt;

&lt;p&gt;If all the reducer functions given to &lt;code&gt;reduceReducers&lt;/code&gt; are called with the top-level state object, but a given feature only needs to apply updates to one piece of the state, we&#39;re going to have a lot of repetitive logic as each feature reducer tries to apply its updates.  In addition, &lt;code&gt;reduceReducers&lt;/code&gt; will be calling these feature reducers will be called on every dispatched action, so it would be nice to ensure the feature reducers only respond if the action is something they care about.&lt;/p&gt;

&lt;p&gt;Putting these ideas together, we can build a higher order reducer function called &lt;code&gt;createConditionalSliceReducer&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/3b5b2bff168f62847f0dcccbce5e1ec096b1fe39&#34;&gt;Commit 3b5b2bf: Add createConditionalSliceReducer utility&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/3b5b2bff168f62847f0dcccbce5e1ec096b1fe39/src/common/utils/reducerUtils.js&#34;&gt;common/utils/reducerUtils.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;
export function createConditionalSliceReducer(sliceName, fnMap) {
    // Create a reducer that knows how to handle one slice of state, with these action types
    const sliceReducer = createReducer({}, fnMap);

    // Create a new wrapping reducer
    return (state, action) =&amp;gt; {
        // Check to see if this slice reducer knows how to handle this action
        if(fnMap[action.type]) {
            // If it does, pass the slice to the slice reducer, and update the slice
            return {
                ...state,
                [sliceName] : sliceReducer(state[sliceName], action),
            };
        }

        // Otherwise, return the existing state unchanged
        return state;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We&#39;ve already seen that our &lt;code&gt;createReducer&lt;/code&gt; utility takes a lookup table mapping action types to case handler reducer functions.  Now, &lt;code&gt;createConditionalSliceReducer&lt;/code&gt; takes the same lookup table, plus the name of a state slice to update.  It uses &lt;code&gt;createReducer&lt;/code&gt; to create a reducer that can handle a single slice, and returns a new reducer that checks incoming actions and only responds if any of the given case reducers know how to handle that action type.&lt;/p&gt;

&lt;h3 id=&#34;creating-a-generic-entity-update-reducer&#34;&gt;Creating a Generic Entity Update Reducer&lt;/h3&gt;

&lt;p&gt;Looking at our Redux-ORM models, we can see that the basic process for updating a given model&#39;s values will be identical no matter what type of model it is.  We need to create a &lt;code&gt;Session&lt;/code&gt; instance, retrieve the right Model class for the item, look up the specific Model instance by ID, and then tell it to queue an update for the given fields.  We can write a generic reducer to update any model instance by its type and ID.&lt;/p&gt;

&lt;p&gt;We&#39;re going to create a new feature folder, &lt;code&gt;features/entities/&lt;/code&gt;, and add the reducer logic there.  We then need to create a top-level &amp;quot;feature reducer&amp;quot; function to execute that logic, and add the feature reducer to our root reducer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/1d5ccae612a97c59782df42680cc3282df31c861&#34;&gt;Commit 1d5ccae6: Add a &amp;quot;entity feature reducer&amp;quot; and a generic &amp;quot;entity update reducer&amp;quot;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/1d5ccae612a97c59782df42680cc3282df31c861/src/features/entities/entityReducer.js&#34;&gt;features/entities/entityReducer&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {ENTITY_UPDATE} from &amp;quot;./entityConstants&amp;quot;;

import {createConditionalSliceReducer} from &amp;quot;common/utils/reducerUtils&amp;quot;;

import schema from &amp;quot;app/schema&amp;quot;;

export function updateEntity(state, payload) {
    const {itemType, itemID, newItemAttributes} = payload;

    const session = schema.from(state);
    const ModelClass = session[itemType];

    let newState = state;

    if(ModelClass.hasId(itemID)) {
        const modelInstance = ModelClass.withId(itemID);

        modelInstance.update(newItemAttributes);

        newState = session.reduce();
    }

    return newState;
}

const entityHandlers = {
    [ENTITY_UPDATE] : updateEntity,
};

const entityCrudFeatureReducer = createConditionalSliceReducer(&amp;quot;entities&amp;quot;, entityHandlers);

export default entityCrudFeatureReducer;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The basic &lt;code&gt;updateEntity()&lt;/code&gt; function should be straightforward.  We extract the &lt;code&gt;itemType&lt;/code&gt;, &lt;code&gt;itemID&lt;/code&gt;, and &lt;code&gt;newItemAttributes&lt;/code&gt; fields from the action payload.  The &lt;code&gt;state&lt;/code&gt; parameter in this case should be &lt;em&gt;just&lt;/em&gt; the &lt;code&gt;entities&lt;/code&gt; slice of our root state.  We create a Redux-ORM Session instance from our &amp;quot;tables&amp;quot;, retrieve the right Model class by name, look up the specific Model instance by ID, and create a new state object with the updates applied.&lt;/p&gt;

&lt;p&gt;From there, we create a lookup table for the action types this module knows how to handle, and use the &lt;code&gt;createConditionalSliceReducer&lt;/code&gt; utility to generate a new reducer that will only respond to the actions in the lookup table, and ensure that only the &lt;code&gt;entities&lt;/code&gt; slice is updated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/1d5ccae612a97c59782df42680cc3282df31c861/src/app/reducers/rootReducer.js&#34;&gt;app/reducers/rootReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import mechsReducer from &amp;quot;features/mechs/mechsReducer&amp;quot;;

+import entityCrudReducer from &amp;quot;features/entities/entityReducer&amp;quot;;

// Omit combined reducer

const rootReducer = reduceReducers(
    combinedReducer,
+   entityCrudReducer,
);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We then add the top-level entity &amp;quot;feature reducer&amp;quot; as another argument to &lt;code&gt;reduceReducers&lt;/code&gt;, and make sure that it&#39;s &lt;em&gt;after&lt;/em&gt; the combined reducer.  Now, &lt;strong&gt;we should be able to dispatch actions to update the contents of any one specific model instance in our state&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&#34;editing-pilot-entries&#34;&gt;Editing Pilot Entries&lt;/h2&gt;

&lt;p&gt;Now that we have our generic entity update reducer in place, we can implement the ability to edit Pilot entries.  We already set up the &amp;quot;start/stop editing&amp;quot; toggle last time, so we just need to hook up the event handlers and dispatch the right actions.&lt;/p&gt;

&lt;h3 id=&#34;hooking-up-pilot-inputs&#34;&gt;Hooking Up Pilot Inputs&lt;/h3&gt;

&lt;p&gt;We&#39;ll start with the Pilot&#39;s &lt;code&gt;name&lt;/code&gt; field:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/762a8205224e2ff4760e5cb87f6428e704f6c539&#34;&gt;Commit 762a820: Hook up editing of pilot name field&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/762a8205224e2ff4760e5cb87f6428e704f6c539/src/features/pilots/PilotDetails/PilotDetails.jsx&#34;&gt;features/pilots/PilotDetails/PilotDetails.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;
+import {updateEntity} from &amp;quot;features/entities/entityActions&amp;quot;;
+import {getValueFromEvent} from &amp;quot;common/utils/clientUtils&amp;quot;;

const actions = {
    startEditingPilot,
    stopEditingPilot,
+   updateEntity,
}

export class PilotDetails  extends Component {
+   onNameChanged = (e) =&amp;gt; {
+       const newValues = getValueFromEvent(e);
+       const {id} = this.props.pilot;
+
+       this.props.updateEntity(&amp;quot;Pilot&amp;quot;, id, newValues);
+   }

// Omit most rendering code

                &amp;lt;Form.Field
                    name=&amp;quot;name&amp;quot;
                    label=&amp;quot;Name&amp;quot;
                    width={16}
                    placeholder=&amp;quot;Name&amp;quot;
                    value={name}
                    disabled={!canStopEditing}
+                   onChange={this.onNameChanged}
                    control=&amp;quot;input&amp;quot;
                /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We import the &lt;code&gt;updateEntity&lt;/code&gt; action creator we just wrote, and add it to the actions that will be bound up to auto-dispatch when called.  We then add an &lt;code&gt;onNameChanged&lt;/code&gt; handler, extract the new values from the change event, and dispatch &lt;code&gt;updateEntity()&lt;/code&gt; by passing in the type of item (&lt;code&gt;&amp;quot;Pilot&amp;quot;&lt;/code&gt;) and the pilot&#39;s ID.&lt;/p&gt;

&lt;p&gt;Let&#39;s try this out by editing one of the pilots.  If we select the pilot named &amp;quot;Miklos Delius&amp;quot;, click &amp;quot;Start Editing&amp;quot;, and type &amp;quot;test&amp;quot; at the end of his name, we should see some actions dispatched:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-7/pilot-name-actions.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-7/pilot-name-actions.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;And there we go!  The dispatched action reached our entities feature reducer, and the &lt;code&gt;updateEntity()&lt;/code&gt; reducer applied the updates to the right data object in the state.  If we look at the screen, we should now see:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-7/pilot-panel-edited.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-7/pilot-panel-edited.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;Because both the form and the list item are displaying the values from the same item in state, both of them have been updated.  It&#39;s important to note that &lt;strong&gt;we are directly editing the values for this Pilot entry in our state&lt;/strong&gt;.  Much of the time, that behavior is &lt;em&gt;not&lt;/em&gt; something we want.  It&#39;s very likely that some parts of the application would still need to display the original data, at the same time that we are making edits to an item.  &lt;strong&gt;We&#39;ll look at one way to handle the &amp;quot;draft/editing data&amp;quot; concept in the next post.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next up is the &amp;quot;Rank&amp;quot; dropdown:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/af7e46e18734902cc202d9a71f22406f31fa812b&#34;&gt;Commit af7e46e: Hook up Pilot &amp;quot;rank&amp;quot; dropdown&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/af7e46e18734902cc202d9a71f22406f31fa812b/src/features/pilots/PilotDetails/PilotDetails.jsx&#34;&gt;features/pilots/PilotDetails/PilotDetails.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;
+   onRankChanged = (e, result) =&amp;gt; {
+       const newValues = {rank : result.value};
+       const {id} = this.props.pilot;
+
+       this.props.updateEntity(&amp;quot;Pilot&amp;quot;, id, newValues);
+   }

// Omit rendering code

                &amp;lt;Form.Field
                    name=&amp;quot;rank&amp;quot;
                    label=&amp;quot;Rank&amp;quot;
                    width={16}
                    control={Dropdown}
                    fluid
                    selection
                    options={RANKS}
                    value={rank}
+                   onChange={this.onRankChanged}
                    disabled={!canStopEditing}
                /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Easy enough, and now we can promote Corporal Delius to be a Sergeant instead.&lt;/p&gt;

&lt;h3 id=&#34;using-generic-change-handlers&#34;&gt;Using Generic Change Handlers&lt;/h3&gt;

&lt;p&gt;We&#39;ve got three more fields that still need to be hooked up (we&#39;ll leave the &amp;quot;Mech&amp;quot; field alone for now).  The &amp;quot;Age&amp;quot; field is another text input, and the &amp;quot;Gunnery&amp;quot; and &amp;quot;Piloting&amp;quot; fields are dropdowns.  We &lt;em&gt;could&lt;/em&gt; write three more individual change handlers for those three fields, but looking at the two we have already, things are pretty simple.  In fact, &lt;code&gt;onNameChanged&lt;/code&gt; doesn&#39;t actually refer to &amp;quot;name&amp;quot; anywhere specifically, and &lt;code&gt;onRankChanged&lt;/code&gt; just references &amp;quot;rank&amp;quot; once as a key.  We could turn those into a generic &amp;quot;text input&amp;quot; handler and a generic &amp;quot;SUI-React Dropdown&amp;quot; handler, and reuse them for all five inputs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/dad0aa71cbb090e3575f351ac54c3d90a20b8ab2&#34;&gt;Commit dad0aa7: Use more generic onChange handlers for PilotDetails dropdowns and inputs&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/dad0aa71cbb090e3575f351ac54c3d90a20b8ab2/src/features/pilots/PilotDetails/PilotDetails.jsx&#34;&gt;features/pilots/PilotDetails/PilotDetails.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;export class PilotDetails  extends Component {
-   onNameChanged = (e) =&amp;gt; {
+   onInputChanged = (e) =&amp;gt; {
        const newValues = getValueFromEvent(e);
        const {id} = this.props.pilot;

        this.props.updateEntity(&amp;quot;Pilot&amp;quot;, id, newValues);
    }

-   onRankChanged = (e, result) =&amp;gt; {
-       const newValues = {rank : result.value};
+    onDropdownChanged = (e, result) =&amp;gt; {
+       const {name, value} = result;
+       const newValues = { [name] : value};
        const {id} = this.props.pilot;

        this.props.updateEntity(&amp;quot;Pilot&amp;quot;, id, newValues);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We then pass the appropriate change handler to each input field, and bam!  All the inputs should now be editable:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-7/pilot-panel-all-edited.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-7/pilot-panel-all-edited.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;h3 id=&#34;buffering-pilot-inputs&#34;&gt;Buffering Pilot Inputs&lt;/h3&gt;

&lt;p&gt;We&#39;ve got one last improvement to make.  The &amp;quot;Name&amp;quot; and &amp;quot;Age&amp;quot; fields are currently unbuffered, and dispatching an &lt;code&gt;ENTITY_UPDATE&lt;/code&gt; action every time we type a key.  We can use our &lt;code&gt;&amp;lt;FormEditWrapper&amp;gt;&lt;/code&gt; component to buffer both of those inputs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/bee1c966ea9cfb67448c79be4039891fe9921fee&#34;&gt;Commit bee1c96: Use FormEditWrapper to buffer changes from Pilot inputs&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/bee1c966ea9cfb67448c79be4039891fe9921fee/src/features/pilots/PilotDetails/PilotDetails.jsx&#34;&gt;features/pilots/PilotDetails/PilotDetails.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;+import FormEditWrapper from &amp;quot;common/components/FormEditWrapper&amp;quot;;

// Omit component and rendering code

+               &amp;lt;FormEditWrapper
+                   singleValue={true}
+                   value={ {name} }
+                   onChange={this.onInputChanged}
+                   passIsEditing={false}
+               &amp;gt;
                    &amp;lt;Form.Field
                        name=&amp;quot;name&amp;quot;
                        label=&amp;quot;Name&amp;quot;
                        width={16}
                        placeholder=&amp;quot;Name&amp;quot;
-                    value={name}
                        disabled={!canStopEditing}
-                    onChange={this.onInputChanged}
                        control=&amp;quot;input&amp;quot;
                    /&amp;gt;
+               &amp;lt;/FormEditWrapper&amp;gt;

+               &amp;lt;FormEditWrapper
+                   singleValue={true}
+                   value={ {age} }
+                   onChange={this.onInputChanged}
+                   passIsEditing={false}
+               &amp;gt;
                    &amp;lt;Form.Field
                        name=&amp;quot;age&amp;quot;
                        width={6}
                        label=&amp;quot;Age&amp;quot;
                        placeholder=&amp;quot;Age&amp;quot;
                        control=&amp;quot;input&amp;quot;
-                   value={age}
-                   onChange={this.onInputChanged}
                        disabled={!canStopEditing}
                    /&amp;gt;
+                &amp;lt;/FormEditWrapper&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, if we edit the name, we should only see a single &lt;code&gt;ENTITY_UPDATE&lt;/code&gt; action get dispatched.&lt;/p&gt;

&lt;h2 id=&#34;final-thoughts&#34;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;We&#39;re now making some significant progress.  The application is starting to become usable, and we&#39;ve used some fairly advanced capabilities and concepts in the process.&lt;/p&gt;

&lt;p&gt;Next time, we&#39;ll deal with the issue of &amp;quot;draft/editing data&amp;quot; for forms, and see how to display the &amp;quot;current&amp;quot; values for an item at the same time that we edit the &amp;quot;work-in-progress&amp;quot; values for that same item.&lt;/p&gt;

&lt;h2 id=&#34;further-information&#34;&gt;Further Information&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek&#34;&gt;Project Mini-Mek repo&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/6&#34;&gt;PR #6: Practical Redux Part 6/7 - WIP branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/7&#34;&gt;PR #7: Practical Redux Part 7 - Final branch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;React Top-Level APIs (children and elements)

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://facebook.github.io/react/docs/react-api.html&#34;&gt;React Docs: React Top-Level API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=DJ53-G8EbxE&#34;&gt;ReactCasts #3: React&#39;s Children API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://callahan.io/blog/2016/09/16/react-dot-children-and-the-react-top-level-api/&#34;&gt;React.Children and the React Top-Level API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://jaketrent.com/post/send-props-to-children-react/&#34;&gt;Send Props to Children in React&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Reducers

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/recipes/StructuringReducers.html&#34;&gt;Redux Docs: Structuring Reducers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/recipes/reducers/SplittingReducerLogic.html&#34;&gt;Structuring Reducers - Splitting Reducer Logic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/recipes/reducers/UsingCombineReducers.html&#34;&gt;Structuring Reducers - Using &lt;code&gt;combineReducers&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/recipes/reducers/BeyondCombineReducers.html&#34;&gt;Structuring Reducers - Beyond &lt;code&gt;combineReducers&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/recipes/reducers/InitializingState.html&#34;&gt;Structuring Reducers - Initializing State&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/faq/Reducers.html#reducers-share-state&#34;&gt;Redux FAQ: Do I have to use &lt;code&gt;combineReducers&lt;/code&gt;?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/acdlite/reduce-reducers&#34;&gt;reduceReducers repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/redux-ecosystem-links/blob/master/reducers.md&#34;&gt;Redux Addons Catalog: Reducers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    
    <item>
      <title>Practical Redux, Part 6: Connected Lists, Forms, and Performance</title>
      <link>https://blog.isquaredsoftware.com/2017/01/practical-redux-part-6-connected-lists-forms-and-performance/</link>
      <pubDate>Tue, 10 Jan 2017 23:00:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2017/01/practical-redux-part-6-connected-lists-forms-and-performance/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/2016/12/practical-redux-part-5-loading-and-displaying-data/&#34;&gt;In Part 5&lt;/a&gt;&lt;/strong&gt;, we added sourcemap support, used Redux-ORM to define and load data, and added some basic item selection tracking.  This time, &lt;strong&gt;we&#39;ll connect lists and forms directly to Redux, discuss performance considerations, implement basic editing capabilities, and add conditional UI state handling&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The code for this project is on Github at &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek&#34;&gt;github.com/markerikson/project-minimek&lt;/a&gt;&lt;/strong&gt;.  The original WIP commits I made for this post can be seen in &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/6&#34;&gt;PR #6: Practical Redux Part 6 WIP&lt;/a&gt;&lt;/strong&gt;, and the final &amp;quot;clean&amp;quot; commits can be seen in in &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/5&#34;&gt;PR #5: Practical Redux Part 6 Final&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I&#39;ll be linking to each &amp;quot;final&amp;quot; commit as I go through the post, as well as specific files in those commits.  I won&#39;t paste every changed file in here or show every single changed line, to save space, but rather try to show the most relevant changes for each commit as appropriate.&lt;/p&gt;

&lt;h3 id=&#34;table-of-contents&#34;&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#connecting-additional-components&#34;&gt;Connecting Additional Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#connected-components-and-performance&#34;&gt;Connected Components and Performance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#connecting-form-components&#34;&gt;Connecting Form Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#pilot-form-ui-state&#34;&gt;Pilot Form UI State&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#final-thoughts&#34;&gt;Final Thoughts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#further-information&#34;&gt;Further Information&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;connecting-additional-components&#34;&gt;Connecting Additional Components&lt;/h2&gt;

&lt;p&gt;Picking up where we left off, we can see that each of our main &amp;quot;panel&amp;quot; components are connected to Redux, as well as the TabBar component.  However, none of the components within those panels are directly connected.  Instead, we&#39;re passing data and action creators down as props from each panel to its children.  It&#39;s perfectly fine to only have a few connected components, but as an app grows, this can become a pain point.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&#34;http://redux.js.org/docs/FAQ.html&#34;&gt;Redux FAQ&lt;/a&gt; covers this topic in the question &lt;a href=&#34;http://redux.js.org/docs/faq/ReactRedux.html#react-multiple-components&#34;&gt;&amp;quot;Should I only connect my top component, or can I connect multiple components in my tree?&amp;quot;&lt;/a&gt;.  Quoting the answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The current suggested best practice is to categorize your components as “presentational” or “container” components, and extract a connected container component wherever it makes sense:&lt;/p&gt;

&lt;p&gt;Emphasizing “one container component at the top” in Redux examples was a mistake. Don&#39;t take this as a maxim. Try to keep your presentation components separate. Create container components by connecting them when it&#39;s convenient. Whenever you feel like you&#39;re duplicating code in parent components to provide data for same kinds of children, time to extract a container. Generally as soon as you feel a parent knows too much about “personal” data or actions of its children, time to extract a container.&lt;/p&gt;

&lt;p&gt;In fact, benchmarks have shown that more connected components generally leads to better performance than fewer connected components.&lt;/p&gt;

&lt;p&gt;In general, try to find a balance between understandable data flow and areas of responsibility with your components.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Following this idea, our next step will be to connect more individual components at a finer-grained level of detail.&lt;/p&gt;

&lt;h3 id=&#34;connecting-the-pilotdetails-component&#34;&gt;Connecting the PilotDetails Component&lt;/h3&gt;

&lt;p&gt;We&#39;ll start with the &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt; component.  Right now, the &lt;code&gt;&amp;lt;Pilots&amp;gt;&lt;/code&gt; component is retrieving a list of all Pilot objects in its &lt;code&gt;mapState&lt;/code&gt; function, plus the &lt;code&gt;currentPilot&lt;/code&gt; ID value.  Then, when it renders, it does a lookup to find which Pilot entry matches the selected ID, and passes that object to &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt;.  We can connect &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt; directly, and remove that logic from &lt;code&gt;&amp;lt;Pilots&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is a straightforward transformation.  We&#39;ll add a &lt;code&gt;mapState&lt;/code&gt; function to &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt;, look up the right Pilot object by ID if available, and return that entry.  While we&#39;re at it, we&#39;ll also tweak the input components to be disabled, so that the user knows they can&#39;t actually interact with them.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/7663759cb37c8146f8413391847fdd080895b18c&#34;&gt;Commit 7663759: Update PilotDetails to be connected&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/7663759cb37c8146f8413391847fdd080895b18c/src/features/pilots/PilotDetails/PilotDetails.jsx&#34;&gt;features/pilots/PilotDetails/PilotDetails.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import React from &amp;quot;react&amp;quot;;
+import {connect} from &amp;quot;react-redux&amp;quot;;
import {Form, Dropdown} from &amp;quot;semantic-ui-react&amp;quot;;

+import schema from &amp;quot;app/schema&amp;quot;;
+import {selectCurrentPilot} from &amp;quot;../pilotsSelectors&amp;quot;;

+const mapState = (state) =&amp;gt; {
+    let pilot;
+    
+    const currentPilot = selectCurrentPilot(state);
+    
+    const session = schema.from(state.entities);
+    const {Pilot} = session;
+    
+    if(Pilot.hasId(currentPilot)) {
+        pilot = Pilot.withId(currentPilot).ref;
+    }
+    
+    return {pilot}
+}

// Omit component code for space

-export default PilotDetails;
+export default connect(mapState)(PilotDetails);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/7663759cb37c8146f8413391847fdd080895b18c/src/features/pilots/Pilots/Pilots.jsx&#34;&gt;features/pilots/Pilots/Pilots.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;    render() {
        const {pilots = [], selectPilot, currentPilot} = this.props;

-       const currentPilotEntry = pilots.find(pilot =&amp;gt; pilot.id === currentPilot) || {}

// Omit irrelevant rendering code
-                           &amp;lt;PilotDetails pilot={currentPilotEntry} /&amp;gt;
+                           &amp;lt;PilotDetails /&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;mapState&lt;/code&gt; connection replaces the logic we had in &lt;code&gt;&amp;lt;Pilots&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&#34;connecting-the-pilotslist-component&#34;&gt;Connecting the PilotsList Component&lt;/h3&gt;

&lt;p&gt;Next up is the &lt;code&gt;&amp;lt;PilotsList&amp;gt;&lt;/code&gt; component.  The &lt;code&gt;&amp;lt;Pilots&amp;gt;&lt;/code&gt; component currently extracts the actual Pilot objects from the store, passes them as an array to &lt;code&gt;&amp;lt;PilotsList&amp;gt;&lt;/code&gt;, and then each individual plain Pilot object is passed as a prop to the &amp;quot;presentational&amp;quot; list items.  We &lt;em&gt;could&lt;/em&gt; just move the current &lt;code&gt;mapState&lt;/code&gt; logic from &lt;code&gt;&amp;lt;Pilots&amp;gt;&lt;/code&gt; to &lt;code&gt;&amp;lt;PilotsList&amp;gt;&lt;/code&gt; and leave it at that, but instead, we&#39;re going to implement &lt;strong&gt;one of the most useful Redux techniques: a connected list that passes item IDs to connected list items&lt;/strong&gt;.  Let&#39;s look at the implementation, then discuss some of the details of the specific approach we&#39;re using.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;mapState&lt;/code&gt; for &lt;code&gt;&amp;lt;PilotsList&amp;gt;&lt;/code&gt; will need to return an array of IDs for all Pilot entries.  &lt;code&gt;&amp;lt;PilotsList&amp;gt;&lt;/code&gt; will then render its list of &lt;code&gt;&amp;lt;PilotsListRow&amp;gt;&lt;/code&gt; components, and pass the appropriate pilot ID into each list item.  Either the list or the list item will need to determine if that list item is currently selected.  There&#39;s valid arguments either way, but since we&#39;re already passing a &lt;code&gt;selected&lt;/code&gt; flag into each list item, we&#39;ll leave that in place.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/dc2c6ab954488317ce035c4284ba293f8ecd3aee&#34;&gt;Commit dc2c6ab: Update PilotsList to be connected&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/dc2c6ab954488317ce035c4284ba293f8ecd3aee/src/features/pilots/PilotsList/PilotsList.jsx&#34;&gt;features/pilots/PilotsList/PilotsList.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;+import {selectPilot} from &amp;quot;../pilotsActions&amp;quot;;
+import {selectCurrentPilot} from &amp;quot;../pilotsSelectors&amp;quot;;
+
+
+const mapState = (state) =&amp;gt; {
+    const session = schema.from(state.entities);
+    const {Pilot} = session;
+
+    // Extract a list of IDs for each Pilot entry
+    const pilots = Pilot.all().withModels.map(pilotModel =&amp;gt; pilotModel.getId());
+
+    const currentPilot = selectCurrentPilot(state);
+
+    // Return the list of pilot IDs and the current pilot ID as props
+    return {pilots, currentPilot};
+}
+
+// Make an object full of action creators that can be passed to connect
+// and bound up, instead of writing a separate mapDispatch function
+const actions = {
+    selectPilot,
+};
+

export class PilotsList extends Component {
    render() {
-      const {pilots, onPilotClicked, currentPilot} = this.props;
+       const {pilots = [], selectPilot, currentPilot} = this.props;

-       const pilotRows = pilots.map(pilot =&amp;gt; (
+       const pilotRows = pilots.map(pilotID =&amp;gt; (
            &amp;lt;PilotsListRow
-               pilot={pilot}
-               key={pilot.name}
-               onPilotClicked={onPilotClicked}
-               selected={pilot.id === currentPilot}
+               pilotID={pilotID}
+               key={pilotID}
+               onPilotClicked={selectPilot}
+               selected={pilotID === currentPilot}
            /&amp;gt;
        ));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;Model.getId()&lt;/code&gt; method is useful if you don&#39;t happen to know the exact name of the ID field for a model type.  Maybe it&#39;s actually &lt;code&gt;name&lt;/code&gt;, or &lt;code&gt;guid&lt;/code&gt;, or something else.  We can declare the ID field name as part of the model declaration, and the &lt;code&gt;getId()&lt;/code&gt; method will use that to look up the right field when asked.&lt;/p&gt;

&lt;p&gt;There&#39;s a few other ways we could come up with the list of Pilot IDs.  Since we &lt;em&gt;do&lt;/em&gt; know the ID field name in the plain Pilot objects, we could do &lt;code&gt;Pilots.all().map(pilot =&amp;gt; pilot.id)&lt;/code&gt;.  Another approach involves digging into Redux-ORM&#39;s internals just a bit.  The &lt;code&gt;QuerySet&lt;/code&gt; class keeps an array of IDs for the entries it&#39;s encapsulating, as a field named &lt;code&gt;idArr&lt;/code&gt;.  So, we could in theory do &lt;code&gt;const pilotIDs = Pilot.all().idArr&lt;/code&gt;, and return that.  Finally, if we wanted to bypass using Redux-ORM&#39;s API, we could directly access the &lt;code&gt;state.entities.Pilot.items&lt;/code&gt; array, where Redux-ORM keeps a list of all Pilot IDs in the state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/dc2c6ab954488317ce035c4284ba293f8ecd3aee/src/features/pilots/PilotsList/PilotsListRow.jsx&#34;&gt;pilots/PilotsList/PilotsListRow.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;+const mapState = (state, ownProps) =&amp;gt; {
+    const session = schema.from(state.entities);
+    const {Pilot} = session;
+
+    let pilot;
+
+    if(Pilot.hasId(ownProps.pilotID)) {
+        const pilotModel = Pilot.withId(ownProps.pilotID);
+
+        // Access the underlying plain JS object using the &amp;quot;ref&amp;quot; field,
+        // and make a shallow copy of it
+        pilot = {
+            ...pilotModel.ref
+        };
+
+        // We want to look up pilotModel.mech.mechType.  Just in case the
+        // relational fields are null, we&#39;ll do a couple safety checks as we go.
+
+        // Look up the associated Mech instance using the foreign-key
+        // field that we defined in the Pilot Model class
+        const {mech} = pilotModel;
+
+        // If there actually is an associated mech, include the
+        // mech type&#39;s ID as a field in the data passed to the component
+        if(mech &amp;amp;&amp;amp; mech.type) {
+            pilot.mechType = mech.type.id;
+        }
+    }
+
+    return {pilot};
+}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For &lt;code&gt;&amp;lt;PilotsListRow&amp;gt;&lt;/code&gt;, we just copy over the lookup logic we had in &lt;code&gt;&amp;lt;Pilots&amp;gt;&lt;/code&gt;, except that now we&#39;re only looking up one entry instead of all of them.  Also, we&#39;re using the &lt;code&gt;pilotID&lt;/code&gt; prop that the &lt;code&gt;&amp;lt;PilotsList&amp;gt;&lt;/code&gt; parent component is passing down.  The connected wrapper component for &lt;code&gt;&amp;lt;PilotsListRow&amp;gt;&lt;/code&gt; makes all passed-in props available to &lt;code&gt;mapState&lt;/code&gt; if we declare that &lt;code&gt;mapState&lt;/code&gt; takes two arguments.  By convention, the second argument is referred to as &lt;code&gt;ownProps&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note that when &lt;code&gt;mapState&lt;/code&gt; is declared to take two arguments, it will be called more often.  This is in case a change of passed-in props would result in a change to the values returned from &lt;code&gt;mapState&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/dc2c6ab954488317ce035c4284ba293f8ecd3aee/src/features/pilots/Pilots/Pilots.jsx&#34;&gt;features/pilots/Pilots/Pilots.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;- // Delete the existing mapState function entirely

-export class Pilots extends Component {
+export default class Pilots extends Component {
    render() {
-        const {pilots = [], selectPilot, currentPilot} = this.props;

        return (
            &amp;lt;Segment&amp;gt;
                &amp;lt;Grid&amp;gt;
                    &amp;lt;Grid.Column width={10}&amp;gt;
                        &amp;lt;Header as=&amp;quot;h3&amp;quot;&amp;gt;Pilot List&amp;lt;/Header&amp;gt;
-                       &amp;lt;PilotsList
-                           pilots={pilots}
-                           onPilotClicked={selectPilot}
-                           currentPilot={currentPilot}
-                       /&amp;gt;
+                       &amp;lt;PilotsList /&amp;gt;
                    &amp;lt;/Grid.Column&amp;gt;

// Omit other rendering logic


-export default connect(mapState, actions)(Pilots);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With those changes in place, the &lt;code&gt;&amp;lt;Pilots&amp;gt;&lt;/code&gt; component is no longer connected, and is actually now back to being entirely presentational.  It renders several layout-related components, and two connected containers: &lt;code&gt;&amp;lt;PilotsList&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&#34;connected-components-and-performance&#34;&gt;Connected Components and Performance&lt;/h2&gt;

&lt;p&gt;The changes to &lt;code&gt;&amp;lt;PilotsList&amp;gt;&lt;/code&gt; bring up a key topic: performance.  There&#39;s several things that are valuable to understand here.&lt;/p&gt;

&lt;h3 id=&#34;basic-performance-considerations&#34;&gt;Basic Performance Considerations&lt;/h3&gt;

&lt;p&gt;By default, whenever a React component re-renders, React will re-render all of its descendents.  That means if the root component were to call &lt;code&gt;this.setState()&lt;/code&gt;, the entire component tree will re-render.  It&#39;s very likely that the majority of components in the tree would receive the exact same data as before and render the same output.  React still has to diff the virtual DOM tree to determine if anything changed, so any render output that didn&#39;t change is effectively &amp;quot;wasted&amp;quot; effort.  (React&#39;s &lt;code&gt;shouldComponentUpdate&lt;/code&gt; method can be used to skip rendering for a component and its descendents, usually by doing comparisons to see if its props have really changed.)&lt;/p&gt;

&lt;p&gt;Redux helps with this by limiting the sub-trees that actually need to re-render.  &lt;code&gt;connect&lt;/code&gt; generates wrapper components that manage subscriptions to the store, and each individual connected component instance is a separate subscriber.  &lt;strong&gt;After each dispatch, every connected component will re-run its &lt;code&gt;mapState&lt;/code&gt; function, and do shallow equality checks on the result to see if the returned values have changed since the last time.  If the values returned by &lt;code&gt;mapState&lt;/code&gt; are different, then the wrapper component will re-render the &amp;quot;real&amp;quot; component&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: &amp;quot;shallow equality&amp;quot; means doing &lt;code&gt;===&lt;/code&gt; reference comparisons on each individual field &lt;strong&gt;within&lt;/strong&gt; the object returned from &lt;code&gt;mapState&lt;/code&gt;.  The return object itself will always be different - what matters is if &lt;code&gt;currentResult.someField === lastResult.someField&lt;/code&gt;, and so on for each field in the object.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&#34;keys-to-good-redux-performance&#34;&gt;Keys to Good Redux Performance&lt;/h3&gt;

&lt;p&gt;This has some important implications:&lt;/p&gt;

&lt;p&gt;First,  &lt;strong&gt;&lt;code&gt;mapState&lt;/code&gt; functions should run as fast as possible&lt;/strong&gt;.  This means that a &lt;code&gt;mapState&lt;/code&gt; function should minimize the amount of work it has to do, and do that work quickly.  &lt;strong&gt;Avoid doing very expensive work in &lt;code&gt;mapState&lt;/code&gt; unless absolutely necessary!&lt;/strong&gt;  This includes complex filtering and transformations.  Memoized selector functions, such as the ones created by &lt;strong&gt;&lt;a href=&#34;https://github.com/reactjs/reselect&#34;&gt;reselect&lt;/a&gt;&lt;/strong&gt;, can ensure that expensive work is only done when something actually changed.&lt;/p&gt;

&lt;p&gt;There&#39;s one very specific performance anti-pattern that involves use of Immutable.js.  According to its author, Lee Byron, &lt;strong&gt;&lt;a href=&#34;https://twitter.com/acemarke/status/806933658204372992&#34;&gt;calling &lt;code&gt;toJS()&lt;/code&gt; is extremely expensive, and should therefore NOT be done in &lt;code&gt;mapState&lt;/code&gt;&lt;/a&gt;!&lt;/strong&gt;.  (There&#39;s several other performance concerns to take into consideration with Immutable.js - see the list of links at the end of this post for more information.)&lt;/p&gt;

&lt;p&gt;Second, &lt;strong&gt;returning the same variable references as part of the &lt;code&gt;mapState&lt;/code&gt; result is necessary to eliminate wasted re-renders&lt;/strong&gt;.  That means that if you&#39;re returning the same types of data at the same keys from &lt;code&gt;mapState&lt;/code&gt;, but the keys point to different variable references each time, &lt;code&gt;connect&lt;/code&gt; will think things have changed and re-render your component.  &lt;strong&gt;One of the most common examples of this is using &lt;code&gt;Array.map()&lt;/code&gt; inside of &lt;code&gt;mapState&lt;/code&gt;&lt;/strong&gt;.  Every time you use &lt;code&gt;map()&lt;/code&gt;, you create a new array reference.  Again, memoized selectors can help with this by ensuring that the same values are returned.&lt;/p&gt;

&lt;p&gt;Third, &lt;strong&gt;overall performance is a balance between the overhead of more &lt;code&gt;mapState&lt;/code&gt; calls, and time spent by React re-rendering&lt;/strong&gt;.  Redux subscriptions are O(n) - every additional subscriber means a bit more work every time an action is dispatched.  Fortunately, per the earlier quote from the FAQ, &lt;strong&gt;benchmarks have shown that the cost of more connected components is generally less than the cost of more wasted re-rendering&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&#34;connected-performance-example&#34;&gt;Connected Performance Example&lt;/h3&gt;

&lt;p&gt;The classic example for examining Redux performance would be a list of 10,000 Todo items.  The basic setup would have only the parent component connected, and directly passing a Todo object to each child.  In this case, editing the text of one Todo will cause the list to re-render, and thus all 10,000 children to re-render as well.&lt;/p&gt;

&lt;p&gt;However, if the list component only passes IDs to each child, and each child is connected and looks up its own Todo item by ID, then most of the time that Todo item will be the same and the list item component won&#39;t need to re-render.  &lt;strong&gt;This is one of several reasons why normalized data is so useful in Redux&lt;/strong&gt;, because normalized data makes it easy to look up a specific item by its type and ID.&lt;/p&gt;

&lt;p&gt;There&#39;s an excellent slideshow called &lt;strong&gt;&lt;a href=&#34;http://somebody32.github.io/high-performance-redux/&#34;&gt;High Performance Redux&lt;/a&gt;&lt;/strong&gt; that discusses this concept in detail, with demos of varying approaches and their performance.&lt;/p&gt;

&lt;h3 id=&#34;performance-concerns-with-project-mini-mek&#34;&gt;Performance Concerns with &lt;em&gt;Project Mini-Mek&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;Based on all that information, let&#39;s do a quick review of our implementation of a connected &lt;code&gt;&amp;lt;PilotsList&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The good news is that we &lt;em&gt;are&lt;/em&gt; using the &amp;quot;connected list passing IDs to connected chilren&amp;quot; pattern.  The bad news is there&#39;s several aspects that are not fully optimized yet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;mapState&lt;/code&gt; for &lt;code&gt;&amp;lt;PilotsList&amp;gt;&lt;/code&gt; is using &lt;code&gt;Array.map()&lt;/code&gt; to create a list of all Pilot IDs.  &lt;strong&gt;That list will be a different array reference every time&lt;/strong&gt;, causing &lt;code&gt;&amp;lt;PilotsList&amp;gt;&lt;/code&gt; to re-render.&lt;/li&gt;
&lt;li&gt;Meanwhile, the &lt;code&gt;mapState&lt;/code&gt; for &lt;code&gt;&amp;lt;PilotsListRow&amp;gt;&lt;/code&gt; is creating a new object for the &lt;code&gt;pilot&lt;/code&gt; prop each time as well, so &lt;code&gt;&amp;lt;PilotsListRow&amp;gt;&lt;/code&gt; will also keep re-rendering&lt;/li&gt;
&lt;li&gt;Neither &lt;code&gt;&amp;lt;PilotsList&amp;gt;&lt;/code&gt; nor &lt;code&gt;&amp;lt;PilotsListRow&amp;gt;&lt;/code&gt; are using any memoized selector functions at all&lt;/li&gt;
&lt;li&gt;We&#39;re also creating a new Redux-ORM &lt;code&gt;Session&lt;/code&gt; instance every time &lt;code&gt;mapState&lt;/code&gt; is run, for each connected component.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fortunately, given the size and scope of &lt;strong&gt;&lt;em&gt;Project Mini-Mek&lt;/em&gt;&lt;/strong&gt;, performance isn&#39;t actually a real concern right now.  Because of that, &lt;strong&gt;we&#39;ll skip performance optimizations for now, and investigate those at a later time.&lt;/strong&gt;  For now, we&#39;ve at least examined some of the major performance concerns to be aware of, and know where to look when it&#39;s time to actually implement optimizations.&lt;/p&gt;

&lt;h3 id=&#34;connecting-the-mechs-components&#34;&gt;Connecting the Mechs Components&lt;/h3&gt;

&lt;p&gt;We&#39;ll wrap up this section by applying the same sets of changes to the various components in the &amp;quot;Mechs&amp;quot; panel as well.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/60c3f291a97bc1088f2bf60ebf9e769e4f90bc10&#34;&gt;Commit 60c3f29: Update MechDetails to be connected&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/bba6aa9b76fab8e8759aab088eb8ba6a4b2eae32&#34;&gt;Commit bba6aa9: Update MechsList to be connected&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;connecting-form-components&#34;&gt;Connecting Form Components&lt;/h2&gt;

&lt;p&gt;Thus far, our application has been non-interactive.  We can currently click on Pilot and Mech list items to select them, but there&#39;s no way to modify anything.  It&#39;s time to start implementing some interactivity.&lt;/p&gt;

&lt;h3 id=&#34;creating-the-form-update-logic&#34;&gt;Creating the Form Update Logic&lt;/h3&gt;

&lt;p&gt;Our first task is to hook up the &lt;code&gt;&amp;lt;UnitInfo&amp;gt;&lt;/code&gt; form so that we can edit the current unit&#39;s name and change what Battletech House or mercenary group they&#39;re affiliated with.  We&#39;ll need to add an action type and a case reducer to handle those updates, then modify &lt;code&gt;&amp;lt;UnitInfo&amp;gt;&lt;/code&gt; so that it dispatches the action in response to &lt;code&gt;onChange&lt;/code&gt; callbacks from the inputs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/7352c4f5c16af242915c81470c2b3c7b44b98a61&#34;&gt;Commit 7352c4f: Implement initial unit info update logic&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The action/reducer changes are simple.  New action type, a matching action creator, and a case reducer:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/7352c4f5c16af242915c81470c2b3c7b44b98a61/src/features/unitInfo/unitInfoReducer.js&#34;&gt;features/unitInfo/unitInfoReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {DATA_LOADED} from &amp;quot;features/tools/toolConstants&amp;quot;;
+import {UNIT_INFO_UPDATE} from &amp;quot;./unitInfoConstants&amp;quot;;

+function updateUnitInfo(state, payload) {
+   return {
+       ...state,
+       ...payload,
+   };
+}

export default createReducer(initialState, {
    [DATA_LOADED] : dataLoaded,
+   [UNIT_INFO_UPDATE] : updateUnitInfo,
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We &lt;em&gt;could&lt;/em&gt; create entirely separate action types and reducers for updating the &amp;quot;Name&amp;quot; field and the &amp;quot;Affiliation&amp;quot; field, but that would be a waste of effort.  &lt;strong&gt;Defining action payloads and reducer logic involves tradeoffs, and it&#39;s up to you to decide when actions should be more specific or more general&lt;/strong&gt;.  I &lt;em&gt;usually&lt;/em&gt; avoid reducers that just blindly copy whatever the action contains, but in this case it&#39;s easy enough to just copy over the payload, and let the dispatching code ensure that the payload is formatted correctly.&lt;/p&gt;

&lt;h3 id=&#34;connecting-a-controlled-input&#34;&gt;Connecting a Controlled Input&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;One of the most important concepts to understand when learning React is the idea of &amp;quot;controlled inputs&amp;quot;&lt;/strong&gt;.  If you&#39;re not familiar with controlled inputs, go read Gosha Arinich&#39;s article &lt;strong&gt;&lt;a href=&#34;https://goshakkk.name/controlled-vs-uncontrolled-inputs-react/&#34;&gt;Controlled and uncontrolled form inputs in React don&#39;t have to be complicated&lt;/a&gt;&lt;/strong&gt;, or the additional articles on forms in React linked at the end of the post.&lt;/p&gt;

&lt;p&gt;As a quick summary, &lt;strong&gt;a controlled input is an input with a &lt;code&gt;value&lt;/code&gt; prop and an &lt;code&gt;onChange&lt;/code&gt; handler&lt;/strong&gt;.  That means that &lt;strong&gt;the input is being &lt;em&gt;told&lt;/em&gt; what its value is at all times, instead of the application asking the input for its value when it&#39;s time to submit the form&lt;/strong&gt;.  Managing controlled inputs does take additional work, but ultimately makes the application much easier to think about, since all the form data is already being stored by the application.&lt;/p&gt;

&lt;p&gt;Values for controlled inputs can be stored by a React component, or passed all the way back to a Redux store.  Since the &lt;code&gt;&amp;lt;UnitInfo&amp;gt;&lt;/code&gt; component is already connected, we just need to pass in the action creator, add an &lt;code&gt;onChange&lt;/code&gt; handler for the &amp;quot;Affiliation&amp;quot; dropdown, and dispatch the action appropriately:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/dc4d179e8ed10f517648d82124f353e6dafda346&#34;&gt;Commit dc4d179: Implement initial change handling for UnitInfo&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/dc4d179e8ed10f517648d82124f353e6dafda346/src/features/unitInfo/UnitInfo/UnitInfo.jsx&#34;&gt;features/unitInfo/UnitInfo/UnitInfo.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;+import {updateUnitInfo} from &amp;quot;../unitInfoActions&amp;quot;;

+const actions = {
+   updateUnitInfo,
+};

class UnitInfo extends Component {
+   onAffiliationChanged = (e, result) =&amp;gt; {
+       const {name, value} = result;
+
+       const newValues = { [name] : value};
+       this.props.updateUnitInfo(newValues);
+   }

// Omit unrelated rendering 

                        &amp;lt;Dropdown
+                           name=&amp;quot;affiliation&amp;quot;
                            selection
                            options={FACTIONS}
                            value={affiliation}
+                           onChange={this.onAffiliationChanged}
                        /&amp;gt;

// Omit rest of component

-export default connect(mapState)(UnitInfo);
+export default connect(mapState, actions)(UnitInfo);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A few things to note about the &lt;code&gt;onAffiliationChanged&lt;/code&gt; handler:&lt;/p&gt;

&lt;p&gt;First, we&#39;re using the &lt;a href=&#34;http://reactkungfu.com/2015/07/why-and-how-to-bind-methods-in-your-react-component-classes/&#34;&gt;stage 2 Class Properties syntax to define an auto-bound method using an arrow function&lt;/a&gt;, so that &lt;code&gt;this&lt;/code&gt; inside the callback correctly refers to the component instance.&lt;/p&gt;

&lt;p&gt;Second, while &lt;a href=&#34;http://react.semantic-ui.com/modules/dropdown&#34;&gt;Semantic-UI-React&#39;s component props documentation&lt;/a&gt; is excellent, they don&#39;t seem to formally document the signature for the &lt;code&gt;&amp;lt;Dropdown&amp;gt;&lt;/code&gt;&#39;s &lt;code&gt;onChange&lt;/code&gt; callback.  After checking some issues such as &lt;a href=&#34;https://github.com/Semantic-Org/Semantic-UI-React/pull/581&#34;&gt;SUI-React #581&lt;/a&gt;, I&#39;ve confirmed that the &lt;code&gt;&amp;lt;Dropdown&amp;gt;&lt;/code&gt; passes two arguments to its &lt;code&gt;onChange&lt;/code&gt; callback: some event object, and a result object that contains the name of the component and its new value (like &lt;code&gt;{name : &amp;quot;affiliation&amp;quot;, value : &amp;quot;wd&amp;quot;}&lt;/code&gt;).  We want to reshape that into something like &lt;code&gt;{affiliation : &amp;quot;wd&amp;quot;}&lt;/code&gt;, so we use the ES6 object computed properties syntax to create the new object.&lt;/p&gt;

&lt;p&gt;Finally, since we used the object shorthand syntax for binding up action creators with &lt;code&gt;connect()&lt;/code&gt;, calling &lt;code&gt;this.props.updateUnitInfo(newValues)&lt;/code&gt; immediately dispatches the action.&lt;/p&gt;

&lt;p&gt;Now, if we go to the Unit Info tab and select &amp;quot;Draconis Combine&amp;quot; from the dropdown, we should see the dispatched action in our DevTools:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-6/unit-affiliation-action.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-6/unit-affiliation-action.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;And the dropdown should now read &amp;quot;Draconis Combine&amp;quot;:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-6/unit-affiliation-display.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-6/unit-affiliation-display.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;From there, we can enable editing the &amp;quot;Name&amp;quot; field with just another change handler:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/2cca3ead0f131ec66714998ff1c0f286dbbc2c28&#34;&gt;Commit 2cca3ea: Hook up unit info name input&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/2cca3ead0f131ec66714998ff1c0f286dbbc2c28/src/features/unitInfo/UnitInfo/UnitInfo.jsx&#34;&gt;features/unitInfo/UnitInfo/UnitInfo.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;+   onNameChanged = (e) =&amp;gt; {
+       const {name, value} = e.target;
+
+       const newValues = { [name] : value};
+       this.props.updateUnitInfo(newValues);
+   }
    
// Omit other rendering

                    &amp;lt;Form.Field name=&amp;quot;name&amp;quot; width={6}&amp;gt;
                        &amp;lt;label&amp;gt;Unit Name&amp;lt;/label&amp;gt;
-                       &amp;lt;input placeholder=&amp;quot;Name&amp;quot; name=&amp;quot;name&amp;quot; value={name}/&amp;gt;
+                       &amp;lt;input
+                           placeholder=&amp;quot;Name&amp;quot;
+                           name=&amp;quot;name&amp;quot;
+                           value={name}
+                           onChange={this.onNameChanged}
+                       /&amp;gt;
                    &amp;lt;/Form.Field&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now we can happily type some gibberish into the &amp;quot;Unit Name&amp;quot; field, and see it show up:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-6/unit-name-display.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-6/unit-name-display.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;So, this is great progress!  We can edit the name and affiliation of our combat unit.&lt;/p&gt;

&lt;h3 id=&#34;retrieving-values-from-input-events&#34;&gt;Retrieving Values from Input Events&lt;/h3&gt;

&lt;p&gt;Right now we&#39;re manually extracting the &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;value&lt;/code&gt; fields from the text input&#39;s &lt;code&gt;onChange&lt;/code&gt; event.  There&#39;s some differences in how HTML inputs structure their events.  Checkboxes in particular use a different field name ( &lt;code&gt;checked&lt;/code&gt; instead of &lt;code&gt;value&lt;/code&gt;).  We can write a small utility function to extract the name and value from events, and do the object formatting for us.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/745eda848672679bee971d2783cd6e4102648d0e&#34;&gt;Commit 745eda8: Add a utility function to extract values from input events&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/745eda848672679bee971d2783cd6e4102648d0e/src/common/utils/clientUtils.js&#34;&gt;common/utils/clientUtils.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {isObject} from &amp;quot;lodash&amp;quot;;

export function getValueFromEvent(e) {
    const {target} = e;

    let newValues;

    if(target) {
        const value = (target.type === &amp;quot;checkbox&amp;quot;) ? target.checked : target.value;
        newValues = {
            [target.name] : value,
        };
    }
    else if(isObject(e)) {
        newValues = e;
    }

    return newValues;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that simplifies our code in &lt;code&gt;&amp;lt;UnitInfo&amp;gt;&lt;/code&gt; a bit:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/745eda848672679bee971d2783cd6e4102648d0e/src/features/unitInfo/UnitInfo/UnitInfo.jsx&#34;&gt;features/unitInfo/UnitInfo/UnitInfo.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;+import {getValueFromEvent} from &amp;quot;common/utils/clientUtils&amp;quot;;


    onNameChanged = (e) =&amp;gt; {
-       const {name, value} = e.target;
-
-       const newValues = { [name] : value};
+       const newValues = getValueFromEvent(e);
        this.props.updateUnitInfo(newValues);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Type in the input, we get back a name/value object as needed, and we dispatch it.  Looks great.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There &lt;em&gt;is&lt;/em&gt; one problem with our text input that we need to address, but we&#39;ll deal with that next time.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&#34;pilot-form-ui-state&#34;&gt;Pilot Form UI State&lt;/h2&gt;

&lt;p&gt;Now that we can edit the basic attributes for our combat unit, it&#39;s time to move on to the Pilots panel.  We want to add the ability to edit the attributes for our individual Pilot entries.  As part of that, it would be nice if we actually could toggle whether we&#39;re in &amp;quot;edit mode&amp;quot; or not.  For now, let&#39;s implement logic to track &amp;quot;editing mode&amp;quot; for pilots, and hold off on actually connecting the inputs until next time.&lt;/p&gt;

&lt;p&gt;We already have logic for tracking which pilot is selected.  To add to that, we should only be able to start editing if a pilot is selected.  If we&#39;re editing one pilot, and click to select another, editing mode should be turned off.&lt;/p&gt;

&lt;h3 id=&#34;tracking-editing-state-for-the-ui&#34;&gt;Tracking Editing State for the UI&lt;/h3&gt;

&lt;p&gt;Let&#39;s start by adding some logic to track whether we&#39;re editing a pilot or not.  We&#39;ll create a couple new action types (&lt;code&gt;PILOT_EDIT_START&lt;/code&gt; and &lt;code&gt;PILOT_EDIT_STOP&lt;/code&gt;), and update our pilots reducer with a new flag and the logic to update it appropriately:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/09fda20959bdcad88252320e2874664c43b3e7a9&#34;&gt;Commit 09fda20: Add logic to track if a pilot is being edited&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/09fda20959bdcad88252320e2874664c43b3e7a9/src/features/pilots/pilotsReducer.js&#34;&gt;features/pilots/pilotsReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {
    PILOT_SELECT,
+   PILOT_EDIT_START,
+   PILOT_EDIT_STOP,
} from &amp;quot;./pilotsConstants&amp;quot;;

const initialState = {
    currentPilot : null,
+   isEditing : false,
};

export function selectPilot(state, payload) {
    const prevSelectedPilot = state.currentPilot;
    const newSelectedPilot = payload.currentPilot;

    const isSamePilot = prevSelectedPilot === newSelectedPilot;
    
    return {
        ...state,
        // Deselect entirely if it&#39;s a second click on the same pilot,
        // otherwise go ahead and select the one that was clicked
        currentPilot : isSamePilot ? null : newSelectedPilot,
+       // Any time we select a different pilot, we stop editing
+       isEditing : false,
    };
}

+export function startEditingPilot(state, payload) {
+   return {
+       ...state,
+       isEditing : true,
+   };
+}

+export function stopEditingPilot(state, payload) {
+   return {
+       ...state,
+       isEditing : false,
+   };
+}


export default createReducer(initialState, {
    [PILOT_SELECT] : selectPilot,
+   [PILOT_EDIT_START] : startEditingPilot,
+   [PILOT_EDIT_STOP] : stopEditingPilot,
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The reducer logic is straightforward.  We respond to &amp;quot;start&amp;quot; and &amp;quot;stop&amp;quot; by setting the &lt;code&gt;isEditing&lt;/code&gt; flag appropriately, and also reset it to false whenever a pilots list entry is clicked.&lt;/p&gt;

&lt;h3 id=&#34;adding-edit-mode-toggles&#34;&gt;Adding Edit Mode Toggles&lt;/h3&gt;

&lt;p&gt;Our next step is adding a pair of &amp;quot;Start / Stop Editing&amp;quot; buttons to the &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt; form, and hooking them up.  We also want to add some conditional logic so that they&#39;re only enabled if appropriate.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/ab6f27eeda5dbc209ceffc51518c05fdc1cef1a5&#34;&gt;Commit ab6f27e: Add &amp;quot;Start/Stop Editing&amp;quot; buttons to PilotDetails&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/ab6f27eeda5dbc209ceffc51518c05fdc1cef1a5/src/features/pilots/PilotDetails/PilotDetails.jsx&#34;&gt;features/pilots/PilotDetails/PilotDetails.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;-import {selectCurrentPilot} from &amp;quot;../pilotsSelectors&amp;quot;;
+import {selectCurrentPilot, selectIsEditingPilot} from &amp;quot;../pilotsSelectors&amp;quot;;

+import {
+   startEditingPilot,
+   stopEditingPilot,
+} from &amp;quot;../pilotsActions&amp;quot;;


const mapState = (state) =&amp;gt; {
    // Omit Pilot object lookup code
 
+   const pilotIsSelected = Boolean(currentPilot);
+   const isEditingPilot = selectIsEditingPilot(state);

-   return {pilot}
+   return {pilot, pilotIsSelected, isEditingPilot}
}

+const actions = {
+    startEditingPilot,
+    stopEditingPilot,
+}


-const PilotDetails = ({pilot={}}) =&amp;gt;{
+const PilotDetails = ({pilot={}, pilotIsSelected = false, isEditingPilot = false, ...actions }) =&amp;gt;{
// Omit attribute lookups

+    const canStartEditing = pilotIsSelected &amp;amp;&amp;amp; !isEditingPilot;
+    const canStopEditing = pilotIsSelected &amp;amp;&amp;amp; isEditingPilot;

    return (
        &amp;lt;Form size=&amp;quot;large&amp;quot;&amp;gt;
            &amp;lt;Form.Field name=&amp;quot;name&amp;quot; width={16}&amp;gt;
                &amp;lt;label&amp;gt;Name&amp;lt;/label&amp;gt;
                &amp;lt;input
                    placeholder=&amp;quot;Name&amp;quot;
                    value={name}
-                   disabled={true}
+                   disabled={!canStopEditing}
                /&amp;gt;
            &amp;lt;/Form.Field&amp;gt;
// Omit other fields
+           &amp;lt;Grid.Row width={16}&amp;gt;
+               &amp;lt;Button
+                   primary
+                   disabled={!canStartEditing}
+                   type=&amp;quot;button&amp;quot;
+                   onClick={actions.startEditingPilot}
+               &amp;gt;
+                   Start Editing
+               &amp;lt;/Button&amp;gt;
+               &amp;lt;Button
+                   secondary
+                   disabled={!canStopEditing}
+                   type=&amp;quot;button&amp;quot;
+                   onClick={actions.stopEditingPilot}
+               &amp;gt;
+                   Stop Editing
+               &amp;lt;/Button&amp;gt;
+           &amp;lt;/Grid.Row&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In our &lt;code&gt;mapState&lt;/code&gt; function, we look at the &lt;code&gt;currentPilot&lt;/code&gt; flag to determine if a pilot is selected or not, and pass that as a prop.  In the component, we look at &lt;code&gt;isEditing&lt;/code&gt; and &lt;code&gt;pilotIsSelected&lt;/code&gt;, and derive two new flags to determine if the &amp;quot;Start&amp;quot; and &amp;quot;Stop&amp;quot; buttons should be enabled.  We also use those to appropriately enable and disable the inputs.&lt;/p&gt;

&lt;p&gt;One other useful note: by default, clicking an HTML &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; inside of a &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; will auto-submit the form.  To avoid that, you have to give the button a &lt;code&gt;type=&amp;quot;button&amp;quot;&lt;/code&gt; attribute.  Real pain in the neck, but now you know :)&lt;/p&gt;

&lt;p&gt;Let&#39;s check out how the form looks now.  If we have data loaded, select a pilot, and click &amp;quot;Start Editing&amp;quot;, we should now see this:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-6/pilot-details-stop-editing.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2017-01-practical-redux-part-6/pilot-details-stop-editing.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;That&#39;s probably a good place to wrap up the work for this post.&lt;/p&gt;

&lt;h2 id=&#34;final-thoughts&#34;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;It took the first few posts to lay a foundation, but we&#39;re now seeing some progress.  We&#39;ve got a good pattern for connecting list components and list items.  We&#39;ve looked at some important performance considerations, and know where we can make performance improvements in the future.  We can now do our first data editing, and we&#39;ve added the ability to toggle the status of some UI components.&lt;/p&gt;

&lt;p&gt;I had to split this post into two parts due to its size, so Part 7 should follow within the next few days.  Part 7 will dig into some advanced techniques for managing form inputs and structuring reducer logic, so be sure to check that out soon!&lt;/p&gt;

&lt;h2 id=&#34;further-information&#34;&gt;Further Information&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek&#34;&gt;Project Mini-Mek repo&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/6&#34;&gt;PR #6: Practical Redux Part 6 - WIP branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/5&#34;&gt;PR #5: Practical Redux Part 6 - Final branch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/faq/ReactRedux.html#react-multiple-components&#34;&gt;Redux FAQ: Should I only connect my top component, or can I connect multiple components?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Performance

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/faq/Performance.html#performance-scaling&#34;&gt;Redux FAQ: How well does Redux &amp;quot;scale&amp;quot; in terms of performance?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/faq/ReactRedux.html#react-mapstate-speed&#34;&gt;Redux FAQ: How can I speed up my &lt;code&gt;mapStateToProps&lt;/code&gt;?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/reactjs/reselect&#34;&gt;Reselect repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://somebody32.github.io/high-performance-redux/&#34;&gt;High Performance Redux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/acemarke/status/806933658204372992&#34;&gt;Twitter: Lee Byron - relative cost of using &lt;code&gt;toJS()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/react-redux-links/blob/master/react-performance.md&#34;&gt;React/Redux Links: Performance (React, Immutable.js, Redux)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/react-redux-links/blob/master/redux-techniques.md#selectors-and-normalization&#34;&gt;React/Redux Links: Redux Techniques - Selectors and Normalization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/recipes/reducers/NormalizingStateShape.html&#34;&gt;Redux Docs: Structuring Reducers - Normalizing State Shape&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Controlled Inputs

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://goshakkk.name/controlled-vs-uncontrolled-inputs-react/&#34;&gt;Controlled and uncontrolled form inputs in React don&#39;t have to be complicated&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://lorenstewart.me/2016/10/31/react-js-forms-controlled-components/&#34;&gt;React Forms - Controlled Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/react-redux-links/blob/master/react-forms.md&#34;&gt;React/Redux Links: React and Forms&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    
    <item>
      <title>Practical Redux, Part 5: Loading and Displaying Data</title>
      <link>https://blog.isquaredsoftware.com/2016/12/practical-redux-part-5-loading-and-displaying-data/</link>
      <pubDate>Mon, 12 Dec 2016 23:00:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2016/12/practical-redux-part-5-loading-and-displaying-data/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/2016/11/practical-redux-part-4-ui-layout-and-project-structure/&#34;&gt;Last time&lt;/a&gt;&lt;/strong&gt;, we built up a hardcoded initial UI layout for &lt;strong&gt;&lt;em&gt;Project Mini-Mek&lt;/em&gt;&lt;/strong&gt; using Semantic-UI-React, added a tab bar component controlled by Redux, and started using a &amp;quot;feature-first&amp;quot;-style folder structure for our code.  This time, &lt;strong&gt;we&#39;ll improve debugging support with sourcemaps, define data models with Redux-ORM, use those models to load data into the store and display it, and add the ability to track which items are selected&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The code for this project is on Github at &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek&#34;&gt;github.com/markerikson/project-minimek&lt;/a&gt;&lt;/strong&gt;.  The original WIP commits I made for this post can be seen in &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/3&#34;&gt;PR #3: Practical Redux Part 5 WIP&lt;/a&gt;&lt;/strong&gt;, and the final &amp;quot;clean&amp;quot; commits can be seen in in &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/4&#34;&gt;PR #4: Practical Redux Part 5 Final&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I&#39;ll be linking to each &amp;quot;final&amp;quot; commit as I go through the post, as well as specific files in those commits.  I won&#39;t paste every changed file in here, to save space, but rather try to show the most relevant changes for each commit as appropriate.&lt;/p&gt;

&lt;h3 id=&#34;table-of-contents&#34;&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#adding-sourcemap-support-for-better-debugging&#34;&gt;Adding Sourcemap Support for Better Debugging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#making-file-structure-consistent&#34;&gt;Making File Structure Consistent&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#extracting-components-in-features&#34;&gt;Extracting Components in Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#adding-a-mock-api-for-sample-data&#34;&gt;Adding a Mock API for Sample Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#connecting-the-unit-info-tab&#34;&gt;Connecting the Unit Info Tab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#adding-a-redux-orm-schema-and-model&#34;&gt;Adding a Redux-ORM Schema and Model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#loading-pilot-data-with-redux-orm&#34;&gt;Loading Pilot Data with Redux-ORM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#displaying-a-list-of-pilots&#34;&gt;Displaying a List of Pilots&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#defining-models-with-relations&#34;&gt;Defining Models with Relations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#displaying-a-list-of-mechs&#34;&gt;Displaying a List of Mechs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#handling-selection-logic&#34;&gt;Handling Selection Logic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#final-thoughts&#34;&gt;Final Thoughts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#further-information&#34;&gt;Further Information&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;adding-sourcemap-support-for-better-debugging&#34;&gt;Adding Sourcemap Support for Better Debugging&lt;/h2&gt;

&lt;p&gt;Before we can start working on the code for this set of improvements, we need to make some library updates that will help improve our development experience, by fixing up a weakness with the debugging process.&lt;/p&gt;

&lt;p&gt;Tools like Webpack and Babel compile our input source code, transform it in various ways, and output a bundle containing all the transformed code in one file.  This is great for production use, since users will load a site faster thanks to smaller files and fewer requests.  However, trying to debug code that&#39;s been compiled, minified, and bundled is just about impossible.  &lt;strong&gt;Fortunately, this can be solved with &lt;a href=&#34;http://blog.teamtreehouse.com/introduction-source-maps&#34;&gt;sourcemaps&lt;/a&gt;, which contain information the debugger can use to show the original code instead of the transformed code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Webpack has many different options for creating sourcemaps, with &lt;a href=&#34;https://lorefnon.me/2016/12/03/on-webpack-and-source-map-integration.html&#34;&gt;varying tradeoffs for speed, details, and contents&lt;/a&gt;.  Up through &lt;a href=&#34;https://github.com/facebookincubator/create-react-app/releases/tag/v0.7.0&#34;&gt;Create-React-App 0.7.0&lt;/a&gt;, CRA configured Webpack to use the &lt;code&gt;eval&lt;/code&gt; sourcemaps option.  That option shows you individual files in the debugger, but shows the code &lt;em&gt;after&lt;/em&gt; it&#39;s been compiled by Babel.  Looking at that in the debugger is better than trying to read minified/bundled code, but it&#39;s not exactly the prettiest, as seen in this screenshot:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-12-practical-redux-part-5/devtools-sourcemaps-eval.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-12-practical-redux-part-5/devtools-sourcemaps-eval.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;The &lt;code&gt;devtool: &amp;quot;eval&amp;quot;&lt;/code&gt; option was chosen because sourcemap support in both browsers and tools hasn&#39;t always worked right, and this option was known to at least produce usable results.&lt;/p&gt;

&lt;p&gt;After a lot of discussion, in &lt;a href=&#34;https://github.com/facebookincubator/create-react-app/releases/tag/v0.8.0&#34;&gt;Create-React-App 0.8.0&lt;/a&gt;, the sourcemaps option was switched to one that should actually show the original code.  &lt;a href=&#34;https://twitter.com/acemarke/status/805216294140317696&#34;&gt;I was extremely excited about this&lt;/a&gt;, but soon ran into a problem - while I could see the code as expected, &lt;a href=&#34;https://twitter.com/acemarke/status/806353019902316545&#34;&gt;I couldn&#39;t set any breakpoints&lt;/a&gt;.  Fortunately, after some further investigation by the CRA and Webpack teams, fixes were made, and &lt;a href=&#34;https://github.com/facebookincubator/create-react-app/releases/tag/v0.8.2&#34;&gt;Create-React-App 0.8.2&lt;/a&gt; was released with &lt;strong&gt;working sourcemap+breakpoints support.&lt;/strong&gt;  &lt;strong&gt;&lt;a href=&#34;https://twitter.com/acemarke/status/806652942866649090&#34;&gt;This made me &lt;em&gt;very&lt;/em&gt; happy :)&lt;/a&gt;&lt;/strong&gt;.  A couple other bug fix releases were put out while I was working on this post, so at the time of writing the latest version is  &lt;strong&gt;&lt;a href=&#34;https://github.com/facebookincubator/create-react-app/releases/tag/v0.8.4&#34;&gt;Create-React-App 0.8.4&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Technically, &lt;code&gt;create-react-app&lt;/code&gt; is just the CLI tool that&#39;s used to create a new project.  The real magic happens in the &lt;code&gt;react-scripts&lt;/code&gt; package, which includes all the build tool configuration.  So, after running &lt;code&gt;yarn add --dev react-scripts@0.8.4&lt;/code&gt; and restarting the development server, the same debugger view should now look like this:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-12-practical-redux-part-5/devtools-sourcemaps-module.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-12-practical-redux-part-5/devtools-sourcemaps-module.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;Notice that we now see the original source code (even the JSX), the DevTools debugger will let us set breakpoints on most of the lines in the file, and we&#39;ve even added a breakpoint and stopped there during a re-render.  &lt;strong&gt;This will make the development experience &lt;em&gt;much&lt;/em&gt; easier as we go along!&lt;/strong&gt;  Definitely time to save that change.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/01c62c6cc60e9889207ceb272e4148bb6b8ca56b&#34;&gt;Commit 01c62c6: Upgrade react-scripts to 0.8.4&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With that upgrade in place, we can now turn our attention back to the code.  We&#39;ll start by completing the file reorganization we worked on last time.&lt;/p&gt;

&lt;h2 id=&#34;making-file-structure-consistent&#34;&gt;Making File Structure Consistent&lt;/h2&gt;

&lt;p&gt;As described in &lt;a href=&#34;https://blog.isquaredsoftware.com/2016/11/practical-redux-part-4-ui-layout-and-project-structure/&#34;&gt;Part 4&lt;/a&gt;, we&#39;re using a &amp;quot;feature-first&amp;quot; folder structure.  However, not all the code qualifies as a &amp;quot;feature&amp;quot;.  There&#39;s really three main divisions:  common code that&#39;s generic and reused throughout the application, code that&#39;s specific to a feature, and the application-level code that ties those features together.&lt;/p&gt;

&lt;p&gt;We&#39;ll do some more file shuffling to reflect those concepts:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/611cb6f8577cf33053d4030c02abd3d991510acc&#34;&gt;Commit 611cb6f: Move core project files to /app for consistency&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After the move, the project file structure now looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;- src
  - app
    - layout
      - App.js, App.css
    - reducers
      - rootReducer.js
    - store
      - configureStore.js
  - common
    - components
    - utils
  - features
    - mechs
    - pilots
    - tabs
    - unitInfo
    - unitOrganization
  - index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;extracting-components-in-features&#34;&gt;Extracting Components in Features&lt;/h2&gt;

&lt;p&gt;The original UI layout we made in Part 4 has a single component for each of the tab panels.  It also has fake data hardcoded right into the UI layout itself.  That&#39;s not going to work well when we start dealing with actual data.  So, before we can work with data, we should extract some components from those panels.&lt;/p&gt;

&lt;p&gt;Looking at our &lt;code&gt;&amp;lt;Pilots&amp;gt;&lt;/code&gt; component, it really consists of two main parts: the list of pilots, and the form showing the details of a single pilot.  It makes sense to extract separate components for each of those, so we&#39;ll split out a &lt;code&gt;&amp;lt;PilotsList&amp;gt;&lt;/code&gt; component and a &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;In addition, the pilots list has a couple different parts.  The header section is static and won&#39;t change.  We could leave that as part of, the render method in &lt;code&gt;&amp;lt;PilotsList&amp;gt;&lt;/code&gt;, but we might as well split it out as a &lt;code&gt;PilotsListHeader&amp;gt;&lt;/code&gt; while we&#39;re at it.  At the same time, we definitely need to be able to render an individual row for each pilot entry, so we&#39;ll create a &lt;code&gt;&amp;lt;PilotsListRow&amp;gt;&lt;/code&gt; component that we can use while rendering the list.&lt;/p&gt;

&lt;p&gt;Since we&#39;re transitioning from hardcoded text in the UI, we should start making use of some kind of sample data.  For the moment, the simplest approach is to treat &lt;code&gt;&amp;lt;Pilots&amp;gt;&lt;/code&gt; as a &amp;quot;container&amp;quot; component, store an array with one item in its state, and pass that down to the list and details components.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/c404584ae486609bd37d38306130a70e7e9d2935&#34;&gt;Commit c404584: Extract components from Pilots panel, and add initial test data&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The main part of our &lt;code&gt;&amp;lt;Pilots&amp;gt;&lt;/code&gt; component now looks like this (skipping library imports):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/c404584ae486609bd37d38306130a70e7e9d2935/src/features/pilots/Pilots/Pilots.jsx&#34;&gt;features/pilots/Pilots/Pilots.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import PilotsList from &amp;quot;../PilotsList&amp;quot;;
import PilotDetails from &amp;quot;../PilotDetails&amp;quot;;

const pilots = [
    {
        name : &amp;quot;Natasha Kerensky&amp;quot;,
        rank : &amp;quot;Captain&amp;quot;,
        age : 52,
        gunnery : 2,
        piloting : 3,
        mechType : &amp;quot;WHM-6R&amp;quot;,
    }
];

export class Pilots extends Component {
    state = {
        pilots : pilots,
    }

    render() {
        const {pilots} = this.state;

        // Use the first pilot as the &amp;quot;current&amp;quot; one for display, if available.
        const currentPilot = pilots[0] || {};

        return (
            &amp;lt;Segment&amp;gt;
                &amp;lt;Grid&amp;gt;
                    &amp;lt;Grid.Column width={10}&amp;gt;
                        &amp;lt;Header as=&amp;quot;h3&amp;quot;&amp;gt;Pilot List&amp;lt;/Header&amp;gt;
                        &amp;lt;PilotsList pilots={pilots} /&amp;gt;
                    &amp;lt;/Grid.Column&amp;gt;
                    &amp;lt;Grid.Column width={6}&amp;gt;
                        &amp;lt;Header as=&amp;quot;h3&amp;quot;&amp;gt;Pilot Details&amp;lt;/Header&amp;gt;
                        &amp;lt;Segment &amp;gt;
                            &amp;lt;PilotDetails pilot={currentPilot} /&amp;gt;
                        &amp;lt;/Segment&amp;gt;
                    &amp;lt;/Grid.Column&amp;gt;
                &amp;lt;/Grid&amp;gt;
            &amp;lt;/Segment&amp;gt;
        );
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Since our Mechs list is effectively identical so far, we&#39;ll do the same set of transformations on that as well.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/6b51219a2273170a29251aeff275c01a7feb849b&#34;&gt;Commit 6b51219: Extract components from Mechs panel, and add initial test data&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There&#39;s one new and useful tidbit to show out of this commit.  In Battletech, a Battlemech can weigh anywhere from 20 to 100 tons, in 5-ton increments.  Mechs are frequently described and grouped based on their &amp;quot;weight class&amp;quot;.  Mechs from 20-35 tons are &amp;quot;Lights&amp;quot;, 40-55 tons are &amp;quot;Mediums&amp;quot;, 60-75 tons are &amp;quot;Heavies&amp;quot;, and a Mech weighing 80-100 tons is an &amp;quot;Assault&amp;quot;.  This is a description that can be derived based on the known weight of a Mech type.  So, we can write a small selector function that takes in a weight value, and returns a description of the weight class:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/6b51219a2273170a29251aeff275c01a7feb849b/src/features/mechs/mechSelectors.js&#34;&gt;features/mechs/mechSelectors.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;const WEIGHT_CLASSES = [
    {name : &amp;quot;Light&amp;quot;, weights : [20, 25, 30, 35]},
    {name : &amp;quot;Medium&amp;quot;, weights : [40, 45, 50, 55]},
    {name : &amp;quot;Heavy&amp;quot;, weights : [60, 65, 70, 75]},
    {name : &amp;quot;Assault&amp;quot;, weights : [80, 85, 90, 95, 100]},
];

export function getWeightClass(weight) {
    const weightClass = WEIGHT_CLASSES.find(wc =&amp;gt; wc.weights.includes(weight)) || {name : &amp;quot;Unknown&amp;quot;};
    return weightClass.name;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Nothing too fancy here.  We define an array with one entry per weight class, and use the &lt;code&gt;Array.find()&lt;/code&gt; method to return the first entry that matches a filter function.  Our filter function uses the &lt;code&gt;Array.includes()&lt;/code&gt; method to see if the given weight value is in the list of weights for that weight class.  If we don&#39;t find a valid weight class, we provide a default result so that we can always &lt;code&gt;return weightClass.name&lt;/code&gt;.  This selector can then be used in &lt;code&gt;&amp;lt;MechsListRow&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;MechDetails&amp;gt;&lt;/code&gt; to provide a display value for the given Mech instance.&lt;/p&gt;

&lt;h2 id=&#34;adding-a-mock-api-for-sample-data&#34;&gt;Adding a Mock API for Sample Data&lt;/h2&gt;

&lt;p&gt;We&#39;re at a point where we need to start working with some data.  In a bigger application or more realistic example, that would probably mean standing up a separate backend server to send back responses, or at least using some kind of &amp;quot;mock API&amp;quot; tool.&lt;/p&gt;

&lt;p&gt;In order to keep this tutorial application as focused as possible, we&#39;re going to follow the classic advice of &lt;a href=&#34;http://www.agilenutshell.com/simplest_thing&#34;&gt;&amp;quot;Do The Simplest Thing That Could Possibly Work&amp;quot;&lt;/a&gt; / &lt;a href=&#34;https://en.wikipedia.org/wiki/You_aren&#39;t_gonna_need_it&#34;&gt;&amp;quot;You Ain&#39;t Gonna Need It&amp;quot;&lt;/a&gt;.  In this case, that means &lt;strong&gt;writing a file to contain our sample data, directly importing it into the source code, and writing a mock API query function that just returns that data in a promise.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We&#39;ll need a bit of UI to actually let us call that mock API function.  Since we&#39;ve already got our tabs bar set up, the simplest way to add some UI is to just create a new panel with a button that fetches the data, and add that as another tab.  We&#39;ll label it the &amp;quot;Tools&amp;quot; panel for now.  It might also make a good place to add &amp;quot;Import&amp;quot; and &amp;quot;Export&amp;quot; buttons down the road.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/db59695446d6342faadbaec11c1af2c6b9c27f78&#34;&gt;Commit db596954: Add a Tools panel and mock API for loading sample data&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The only really interesting bits of out of here are the initial sample data, the mock API function, and our thunk action creator:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/db59695446d6342faadbaec11c1af2c6b9c27f78/src/data/sampleData.js&#34;&gt;data/sampleData.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;const sampleData = {
    unit : {
        name : &amp;quot;Black Widow Company&amp;quot;,
        affiliation : &amp;quot;wd&amp;quot;,
    },
};

export default sampleData;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/db59695446d6342faadbaec11c1af2c6b9c27f78/src/data/mockAPI.js&#34;&gt;data/mockAPI.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import sampleData from &amp;quot;./sampleData&amp;quot;;

export function fetchData() {
    return Promise.resolve(sampleData);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/db59695446d6342faadbaec11c1af2c6b9c27f78/src/features/tools/toolActions.js&#34;&gt;features/tools/toolActions.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {fetchData} from &amp;quot;data/mockAPI&amp;quot;;

import {DATA_LOADED} from &amp;quot;./toolConstants&amp;quot;;

export function loadUnitData() {
    return (dispatch, getState) =&amp;gt; {
        fetchData()
            .then(data =&amp;gt; {
                dispatch({
                    type : DATA_LOADED,
                    payload : data
                })
            });
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After adding the panel, the UI looks like this:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-12-practical-redux-part-5/tools-panel.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-12-practical-redux-part-5/tools-panel.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;Feel the excitement! :)&lt;/p&gt;

&lt;h2 id=&#34;connecting-the-unit-info-tab&#34;&gt;Connecting the Unit Info Tab&lt;/h2&gt;

&lt;p&gt;It&#39;s time to start hooking up some of our UI to the store.  We&#39;ll start with the simplest part: the Unit Info tab.  First, a bit of background info - it would be helpful to know what a &amp;quot;unit&amp;quot; is.&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;http://www.sarna.net/wiki/Inner_Sphere_Military_Structure&#34;&gt;A Battletech &amp;quot;unit&amp;quot; is a military group&lt;/a&gt;, which could be part of the official armed forces of one of the various &amp;quot;star nations&amp;quot; in the Battletech universe, or an independent combat group like a mercenary unit.  The five &lt;a href=&#34;http://www.sarna.net/wiki/Successor_States&#34;&gt;Great Houses&lt;/a&gt; in the Battletech universe all maintain vast armies, while hundreds of &lt;a href=&#34;http://www.sarna.net/wiki/Mercenary_unit&#34;&gt;mercenary units&lt;/a&gt; large and small try to make a living through combat.  Some examples of units from the game universe include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Great House army units:

&lt;ul&gt;
&lt;li&gt;24th Dieron Regulars from the Draconis Combine&lt;/li&gt;
&lt;li&gt;2nd Free Worlds Guards from the Free Worlds League&lt;/li&gt;
&lt;li&gt;11th Avalon Hussars from the Federated Suns&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Mercenaries:

&lt;ul&gt;
&lt;li&gt;Wolf&#39;s Dragoons&lt;/li&gt;
&lt;li&gt;21st Centauri Lancers&lt;/li&gt;
&lt;li&gt;Hansen&#39;s Roughriders&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For now, we&#39;re just going to track two attributes for a unit: their name, and what larger group they are affiliated with.&lt;/p&gt;

&lt;p&gt;We&#39;ll start by creating a simple reducer that stores the &amp;quot;Name&amp;quot; and &amp;quot;Affiliation&amp;quot; values, add that to our root reducer, and connect the &lt;code&gt;&amp;lt;UnitInfo&amp;gt;&lt;/code&gt; component to use the data:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/bce3a2d3d4220eb0d80c2bc1d5c7ecc97c0c1e75&#34;&gt;Commit bce3a2d: Add initial unit info reducer and connection&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/bce3a2d3d4220eb0d80c2bc1d5c7ecc97c0c1e75/src/features/unitInfo/unitInfoReducer.js&#34;&gt;features/unitInfo/unitInfoReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {createReducer} from &amp;quot;common/utils/reducerUtils&amp;quot;;

const initialState = {
    name : &amp;quot;Black Widow Company&amp;quot;,
    affiliation : &amp;quot;wd&amp;quot;,
};

export default createReducer(initialState, {
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/bce3a2d3d4220eb0d80c2bc1d5c7ecc97c0c1e75/src/features/unitInfo/unitInfoSelectors.js&#34;&gt;features/unitInfo/unitInfoSelectors.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;export const selectUnitInfo = state =&amp;gt; state.unitInfo;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/bce3a2d3d4220eb0d80c2bc1d5c7ecc97c0c1e75/src/app/reducers/rootReducer.js&#34;&gt;app/reducers/rootReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {combineReducers} from &amp;quot;redux&amp;quot;;

import tabReducer from &amp;quot;features/tabs/tabReducer&amp;quot;;
import unitInfoReducer from &amp;quot;features/unitInfo/unitInfoReducer&amp;quot;;

const rootReducer = combineReducers({
    unitInfo : unitInfoReducer,
    tabs : tabReducer,
});

export default rootReducer;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/bce3a2d3d4220eb0d80c2bc1d5c7ecc97c0c1e75/src/features/unitInfo/UnitInfo/UnitInfo.jsx&#34;&gt;features/unitInfo/UnitInfo/UnitInfo.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;const mapState = (state) =&amp;gt; ({
    unitInfo : selectUnitInfo(state),
});

class UnitInfo extends Component {
    render() {
        const {unitInfo} = this.props;
        const {name, affiliation} = unitInfo;

        return (
            &amp;lt;Segment attached=&amp;quot;bottom&amp;quot;&amp;gt;
                &amp;lt;Form size=&amp;quot;large&amp;quot;&amp;gt;
                    &amp;lt;Form.Field name=&amp;quot;name&amp;quot; width={6}&amp;gt;
                        &amp;lt;label&amp;gt;Unit Name&amp;lt;/label&amp;gt;
                        &amp;lt;input placeholder=&amp;quot;Name&amp;quot; value={name}/&amp;gt;
                    &amp;lt;/Form.Field&amp;gt;
                    &amp;lt;Form.Field name=&amp;quot;affiliation&amp;quot; width={6}&amp;gt;
                        &amp;lt;label&amp;gt;Affiliation&amp;lt;/label&amp;gt;
                        &amp;lt;Dropdown
                            selection
                            options={FACTIONS}
                            value={affiliation}
                        /&amp;gt;
                    &amp;lt;/Form.Field&amp;gt;
                &amp;lt;/Form&amp;gt;
            &amp;lt;/Segment&amp;gt;
        );
    }
}

export default connect(mapState)(UnitInfo);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(Side note: remember how I said I&#39;m still trying to figure out my own best practices for folder structure?  After that last code sample, I definitely have to admit that having the word &amp;quot;unitInfo&amp;quot; show up three times in a path is kinda silly.  Oh well, I&#39;ll deal with it for now.)&lt;/p&gt;

&lt;p&gt;Now that the &lt;code&gt;&amp;lt;UnitInfo&amp;gt;&lt;/code&gt; component is being driven by data from the store, we can do something with that sample data from the mock API.  Let&#39;s update the unit info reducer to respond to the &lt;code&gt;DATA_LOADED&lt;/code&gt; action and see what happens:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/3ccddf180c939351fa8074144d9e2a4c97f60621&#34;&gt;Commit 3ccddf1: Load unit details from sample data&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/3ccddf180c939351fa8074144d9e2a4c97f60621/src/features/unitInfo/unitInfoReducer.js&#34;&gt;features/unitInfo/unitInfoReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {createReducer} from &amp;quot;common/utils/reducerUtils&amp;quot;;

import {DATA_LOADED} from &amp;quot;features/tools/toolConstants&amp;quot;;

const initialState = {
    name : &amp;quot;N/A&amp;quot;,
    affiliation : &amp;quot;&amp;quot;,
};

function dataLoaded(state, payload) {
    const {unit} = payload;

    return unit;
}

export default createReducer(initialState, {
    [DATA_LOADED] : dataLoaded,
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The reducer&#39;s very simple for now.  We start with some empty data in our initial state, listen for &lt;code&gt;DATA_LOADED&lt;/code&gt;, and return the &lt;code&gt;unit&lt;/code&gt; data from the action payload.&lt;/p&gt;

&lt;p&gt;If we load the page, we should see &amp;quot;Name: N/A&amp;quot;.  If we then click the &amp;quot;Reload Unit Data&amp;quot; button in the Tools tab, we should see it change to &amp;quot;Name: Black Widow Company&amp;quot;.  No point in showing a screenshot here, because the UI should still look exactly the same as it has up until now.&lt;/p&gt;

&lt;h2 id=&#34;adding-a-redux-orm-schema-and-model&#34;&gt;Adding a Redux-ORM Schema and Model&lt;/h2&gt;

&lt;p&gt;Okay, so loading two fields was pretty easy.  It&#39;s time to start actually working out what the application&#39;s data model will look like.&lt;/p&gt;

&lt;p&gt;As described back in &lt;a href=&#34;https://blog.isquaredsoftware.com/2016/10/practical-redux-part-0-introduction/&#34;&gt;Part 0&lt;/a&gt; and &lt;a href=&#34;https://blog.isquaredsoftware.com/2016/11/practical-redux-part-3-project-planning-and-setup/&#34;&gt;Part 3&lt;/a&gt;, the goal of this sample application is to build a miniature version of the Battletech &lt;a href=&#34;http://megamek.info/mekhq&#34;&gt;MekHQ game tool&lt;/a&gt;.  &lt;strong&gt;We want to be able to track Battlemech Pilots assigned to a combat unit, which specific Battlemech each Pilot is assigned to, and ultimately organize Battlemechs and their Pilots into groups called &amp;quot;Lances&amp;quot; and &amp;quot;Companies&amp;quot;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We&#39;re going to use the &lt;a href=&#34;https://github.com/tommikaikkonen/redux-orm&#34;&gt;Redux-ORM&lt;/a&gt; library to help define what our data types are and how they relate to each other.  Those Model types can then be used to help us load data into our store, and query and update that data.  (See &lt;strong&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/2016/10/practical-redux-part-0-introduction/&#34;&gt;Part 1: Redux-ORM Basics&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/2016/10/practical-redux-part-0-introduction/&#34;&gt;Part 2: Redux-ORM Concepts and Techniques&lt;/a&gt;&lt;/strong&gt; for details on how the library works.)&lt;/p&gt;

&lt;p&gt;The first thing we&#39;ll do is &lt;strong&gt;create a Redux-ORM Schema instance, and a parent reducer for all of our entity data&lt;/strong&gt;.  Since this code isn&#39;t specific to a single feature, we&#39;ll add it underneath the &lt;code&gt;app&lt;/code&gt; folder.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/1e48ca2a59acbdc3f1203e231e6637a619893345&#34;&gt;Commit 1e48ca2: Create a Redux-ORM Schema and the initial entities reducer&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/1e48ca2a59acbdc3f1203e231e6637a619893345/src/app/schema/schema.js&#34;&gt;app/schema/schema.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {Schema} from &amp;quot;redux-orm&amp;quot;;

const schema = new Schema();

export default schema;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/1e48ca2a59acbdc3f1203e231e6637a619893345/src/app/reducers/entitiesReducer.js&#34;&gt;app/reducers/entitiesReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {createReducer} from &amp;quot;common/utils/reducerUtils&amp;quot;;

import schema from &amp;quot;app/schema&amp;quot;

const initialState = schema.getDefaultState();

export default createReducer(initialState, {
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/1e48ca2a59acbdc3f1203e231e6637a619893345/src/app/reducers/rootReducer.js&#34;&gt;app/reducers/rootReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {combineReducers} from &amp;quot;redux&amp;quot;;

+import entitiesReducer from &amp;quot;./entitiesReducer&amp;quot;;
import tabReducer from &amp;quot;features/tabs/tabReducer&amp;quot;;
import unitInfoReducer from &amp;quot;features/unitInfo/unitInfoReducer&amp;quot;;

const rootReducer = combineReducers({
+   entities : entitiesReducer,
    unitInfo : unitInfoReducer,
    tabs : tabReducer,
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we look at our overall app state now using the Redux DevTools, we&#39;ll see &lt;code&gt;entities: {}&lt;/code&gt;.  That&#39;s because we haven&#39;t added any Model types to the Schema instance.&lt;/p&gt;

&lt;p&gt;The first Model type we should add is for pilots.  We&#39;ll keep it &lt;em&gt;really&lt;/em&gt; simple - just a Pilot class, with no relations, and add that to our Schema.  There&#39;s no specific rule for where Model classes should be defined, so for the moment we&#39;re going to define them inside the relevant feature folders.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/4ca88bd3bad4d7c12f8de77f94af88430e081d89&#34;&gt;Commit 4ca88bd: Create Pilot model and add to schema&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/4ca88bd3bad4d7c12f8de77f94af88430e081d89/src/features/pilots/Pilot.js&#34;&gt;features/pilots/Pilot.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {Model} from &amp;quot;redux-orm&amp;quot;;

export default class Pilot extends Model {
}

Pilot.modelName = &amp;quot;Pilot&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/4ca88bd3bad4d7c12f8de77f94af88430e081d89/src/app/schema/schema.js&#34;&gt;app/schema/schema.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {Schema} from &amp;quot;redux-orm&amp;quot;;

+import Pilot from &amp;quot;features/pilots/Pilot&amp;quot;;

const schema = new Schema();
+schema.register(Pilot);

export default schema;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now that we have the Pilot model class registered with the Schema instance, we can go back to the Redux DevTools and see that the generated initial state for our &lt;code&gt;entities&lt;/code&gt; slice reducer now includes an empty &amp;quot;table&amp;quot; for the Pilot type:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-12-practical-redux-part-5/devtools-pilot-empty.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-12-practical-redux-part-5/devtools-pilot-empty.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;h2 id=&#34;loading-pilot-data-with-redux-orm&#34;&gt;Loading Pilot Data with Redux-ORM&lt;/h2&gt;

&lt;p&gt;With the Pilot model hooked up to the Schema, we can start using it for something useful.  We already have a sample data file and a &lt;code&gt;DATA_LOADED&lt;/code&gt; action being dispatched containing that data.  Let&#39;s add some pilot entries to that list, and load them into memory.&lt;/p&gt;

&lt;p&gt;For sample entries, we&#39;re going to use the characters from the legendary &lt;a href=&#34;http://www.sarna.net/wiki/Black_Widow_Company&#34;&gt;Black Widow Company of the Wolf&#39;s Dragoons mercenary unit&lt;/a&gt;, as they existed in the 3025 game era.  This group was led by the notorious Black Widow herself, &lt;a href=&#34;http://www.sarna.net/wiki/Natasha_Kerensky&#34;&gt;Natasha Kerensky&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We&#39;ll define several attributes for each pilot: an ID, their name, rank, age, in-game Gunnery and Piloting skills (lower is better), and a short description of what type of Battlemech they pilot.  An example looks like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;{
    pilots: [
        {
            id : 1,
            name : &amp;quot;Natasha Kerensky&amp;quot;,
            rank : &amp;quot;Captain&amp;quot;,
            gunnery : 2,
            piloting : 2,
            age : 52,
            mechType : &amp;quot;WHM-6R&amp;quot;,
        },
        {
            id : 2,
            name : &amp;quot;Colin Maclaren&amp;quot;,
            rank : &amp;quot;Sergeant&amp;quot;,
            gunnery : 3,
            piloting : 4,
            age : 43,
            mechType : &amp;quot;MAD-3R&amp;quot;,
        },
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once those entries have been added to the sample data, they wil be included in the &lt;code&gt;DATA_LOADED&lt;/code&gt; action we&#39;ve been dispatching.  So, we should update our &lt;code&gt;entitiesReducer&lt;/code&gt; to respond to that action.&lt;/p&gt;

&lt;p&gt;Redux-ORM provides methods on Model instances to query, update, and delete instances.  It also provides a &lt;code&gt;create&lt;/code&gt; static method on the class itself to create new instances.  I like to write &lt;code&gt;parse&lt;/code&gt; methods on my Model classes that encapsulate the logic for handling all the relations that might be involved in nested JSON data.  Since this is our first Model type, there&#39;s actually nothing special we need to do:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/04a67852f08ac5e62262a7dc552d1d821543d1bb&#34;&gt;Commit 04a6785: Add Pilot parsing, and load Pilots from sample data&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/04a67852f08ac5e62262a7dc552d1d821543d1bb/src/features/pilots/Pilot.js&#34;&gt;features/pilots/Pilot.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {Model} from &amp;quot;redux-orm&amp;quot;;

export default class Pilot extends Model {
    static parse(pilotData) {
        // We could do useful stuff in here with relations,
        // but since we have no relations yet, all we need
        // to do is pass the pilot data on to create()

        // Note that in a static class method, `this` is the
        // class itself, not an instance
        return this.create(pilotData);
    }
}

Pilot.modelName = &amp;quot;Pilot&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/04a67852f08ac5e62262a7dc552d1d821543d1bb/src/app/reducers/entitiesReducer.js&#34;&gt;app/reducers/entitiesReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;export function loadData(state, payload) {
    // Create a Redux-ORM session from our entities &amp;quot;tables&amp;quot;
    const session = schema.from(state);
    // Get a reference to the correct version of the Pilots class for this Session
    const {Pilot} = session;

    const {pilots} = payload;
    // Queue up creation commands for each pilot entry
    pilots.forEach(pilot =&amp;gt; Pilot.parse(pilot));

    // Apply the queued updates and return the updated &amp;quot;tables&amp;quot;
    return session.reduce();
}

export default createReducer(initialState, {
    [DATA_LOADED] : loadData,
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Notice that we actually have two different slice reducers responding to the same action!&lt;/strong&gt;  Both our &lt;code&gt;unitInfoReducer&lt;/code&gt; and our &lt;code&gt;entitiesReducer&lt;/code&gt; are responding to the &lt;code&gt;DATA_LOADED&lt;/code&gt; action.  &lt;strong&gt;This is a key concept for Redux usage, which is often misunderstood or ignored&lt;/strong&gt;.  It doesn&#39;t happen by accident, or completely automatically - the &lt;code&gt;combineReducers&lt;/code&gt; function we&#39;re using in our &lt;code&gt;rootReducer&lt;/code&gt; is specifically calling both slice reducers, and giving them a chance to respond to that action by updating their own slice of data.  We could implement the same behavior ourselves, but &lt;code&gt;combineReducers&lt;/code&gt; does it for us.  (&lt;strong&gt;We could also choose &lt;em&gt;not&lt;/em&gt; to use &lt;code&gt;combineReducers&lt;/code&gt; if we wanted to, and maybe handle things a different way if it made sense.&lt;/strong&gt;)&lt;/p&gt;

&lt;p&gt;If we hit the &amp;quot;Reload Unit Data&amp;quot; button in our &amp;quot;Tools&amp;quot; tab and check out the results in the DevTools, our &lt;code&gt;entities&lt;/code&gt; slice should now contain entries for each of the pilot entries in our sample data:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-12-practical-redux-part-5/devtools-pilot-full.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-12-practical-redux-part-5/devtools-pilot-full.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;&lt;strong&gt;Also notice that Redux-ORM automatically stored all the pilots in &amp;quot;normalized&amp;quot; form&lt;/strong&gt;, by creating an &lt;code&gt;items&lt;/code&gt; array for the Pilot type that stores a list of all item IDs, and an &lt;code&gt;itemsById&lt;/code&gt; lookup table that stores the actual objects keyed by their IDs&lt;/p&gt;

&lt;h2 id=&#34;displaying-a-list-of-pilots&#34;&gt;Displaying a List of Pilots&lt;/h2&gt;

&lt;p&gt;Now that we have pilots added to the store, we can update our &lt;code&gt;&amp;lt;Pilots&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;PilotsList&amp;gt;&lt;/code&gt; components to display them.  Since we already had &lt;code&gt;&amp;lt;Pilots&amp;gt;&lt;/code&gt; acting as a container component, all we really need to do is connect it to the store, return an array of plain JS pilot objects as a prop, and switch from using the sample entry we had stored in its state to the array from props.&lt;/p&gt;

&lt;p&gt;To do this, we&#39;re going to import the singleton Redux-ORM Schema instance we created.  In our &lt;code&gt;mapState&lt;/code&gt; function, we&#39;ll create a Session instance from the current set of &amp;quot;tables&amp;quot; in our state, and use the Pilot class we defined to query those tables.  We&#39;ll  retrieve a list of the actual JS objects, and return those as a prop.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/5e2b5d5ce3541d75ebd00f30a2e222e54eb1748b&#34;&gt;Commit 5e2b5d5: Connect the Pilots component to render a list of pilots from the store&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/5e2b5d5ce3541d75ebd00f30a2e222e54eb1748b/src/features/pilots/Pilots/Pilots.jsx&#34;&gt;features/pilots/Pilots/Pilots.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;// Omit imports not relevant to this commit
import schema from &amp;quot;app/schema&amp;quot;;

const mapState = (state) =&amp;gt; {
    // Create a Redux-ORM Session from our &amp;quot;entities&amp;quot; slice, which
    // contains the &amp;quot;tables&amp;quot; for each model type
    const session = schema.from(state.entities);

    // Retrieve the model class that we need.  Each Session
    // specifically &amp;quot;binds&amp;quot; model classes to itself, so that
    // updates to model instances are applied to that session.
    // These &amp;quot;bound classes&amp;quot; are available as fields in the sesssion.
    const {Pilot} = session;

    // Query the session for all Pilot instances.
    // The QuerySet that is returned from all() can be used to
    // retrieve instances of the Pilot class, or retrieve the
    // plain JS objects that are actually in the store.
    // The toRefArray() method will give us an array of the
    // plain JS objects for each item in the QuerySet.
    const pilots = Pilot.all().toRefArray();

    // Now that we have an array of all pilot objects, return it as a prop
    return {pilots};
}

export class Pilots extends Component {
    render() {
        const {pilots = []} = this.props;

        // Use the first pilot as the &amp;quot;current&amp;quot; one for display, if available.
        const currentPilot = pilots[0] || {};
        
        // Omit rendering code, which didn&#39;t change
    }
}
       
export default connect(mapState)(Pilots);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And with that, we finally have something useful and interesting displayed on screen!&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-12-practical-redux-part-5/pilots-list.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-12-practical-redux-part-5/pilots-list.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;h2 id=&#34;defining-models-with-relations&#34;&gt;Defining Models with Relations&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Redux-ORM allows you to define relations between various model types, using standard database concepts&lt;/strong&gt;.  This is done by adding a &lt;code&gt;fields&lt;/code&gt; entry on a Model class type itself, and using the relation operators provided by Redux-ORM.  Also, as described in &lt;strong&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/2016/10/practical-redux-part-2-redux-orm-concepts-and-techniques/&#34;&gt;Part 2&lt;/a&gt;&lt;/strong&gt;, when a Model instance is created Redux-ORM will generate getter properties for all fields in the actual data object, as well as all of the relational fields.&lt;/p&gt;

&lt;p&gt;With those ideas in mind, we&#39;re almost ready to define our next couple Model types, but first we need to review a bit more information about the ideas we&#39;re trying to represent.  &lt;strong&gt;In Battletech, there are many different Battlemech designs&lt;/strong&gt;.  Each design has different statistics: weight, speed, armor, weapons, and so on.  There may also be different variations on the same design, which would share the same basic characteristics (usually weight and speed), but maybe have some differences in weapons and armor.  &lt;strong&gt;There can be many different individual mechs of the same design&lt;/strong&gt;.  Here&#39;s some examples of different Battlemech design variants to give you the idea:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Stinger STG-3R&lt;/strong&gt;: 20 tons; 6/9/6 movement points (walk/run/jump); 48 armor points;  1 Medium Laser and 2 Machine Guns&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stinger STG-3G&lt;/strong&gt;: 20 tons; 6/9/6 movement points; 69 armor points; 2 Medium Lasers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Warhammer WHM-6R&lt;/strong&gt;: 70 tons; 4/6 movement points; 160 armor points; 2 PPCs, 2 Medium Lasers, 2 Small Lasers, 1 SRM-6 launcher&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Warhammer WHM-6D&lt;/strong&gt;: 70 tons; 4/6 movement points; 217 armor points; 2 PPCs, 2 Medium Lasers, 2 Small Lasers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a real-life comparison, the F-15 Eagle has several variants: the F-15C is made for air-to-air combat, the F-15D is a training version, the F-15E is intended for ground attacks, and hundreds of individual F-15s have been manufactured.&lt;/p&gt;

&lt;p&gt;For our data modeling, we&#39;re going to create two more Model classes.  We&#39;re going to need to store information on different Battlemech designs, and we also need to track individual mechs.  Rather than copy all the attributes of a design into each individual Mech entry, we can just store the design once, and add a relation between the individual Mech and its design entry.  Meanwhile, since Pilots are going to be assigned to Mechs, we would also want to be able to relate Pilots and Mechs to each other.&lt;/p&gt;

&lt;p&gt;Based on that, &lt;strong&gt;we&#39;re going to create separate models for MechDesigns and Mechs&lt;/strong&gt;.  &lt;strong&gt;The Mech class will use &amp;quot;foreign key&amp;quot; relations to point to a MechDesign instance and a Pilot instance&lt;/strong&gt;.  For now, we&#39;ll also add an FK relation from Pilot to Mech so that we can look up the Mech instance that a given Pilot is assigned to.  We&#39;ll also go ahead and create &lt;code&gt;parse()&lt;/code&gt; methods on them so that we can load them from data.  Finally, we&#39;ll add the Mech and MechDesign classes to our Schema instance, the same way we did with Pilot.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/f28fee9a98c7a5efa456c7e20f1906dca4431ae7&#34;&gt;Commit f28fee9: Define Mech and MechDesign model classes, and add them to the schema&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/f28fee9a98c7a5efa456c7e20f1906dca4431ae7/src/features/mechs/MechDesign.js&#34;&gt;features/mechs/MechDesign.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {Model} from &amp;quot;redux-orm&amp;quot;;

export default class MechDesign extends Model {
    static parse(designData) {
        return this.create(designData);
    }
}

MechDesign.modelName = &amp;quot;MechDesign&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/f28fee9a98c7a5efa456c7e20f1906dca4431ae7/src/features/mechs/Mech.js&#34;&gt;features/mechs/Mech.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {Model, fk} from &amp;quot;redux-orm&amp;quot;;


export default class Mech extends Model {
    static get fields() {
        return {
            type : fk(&amp;quot;MechDesign&amp;quot;),
            pilot : fk(&amp;quot;Pilot&amp;quot;),
        };
    }
    
    static parse(mechData) {
        return this.create(mechData);
    }
}

Mech.modelName = &amp;quot;Mech&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(The &lt;code&gt;fields&lt;/code&gt; option could have been defined as &lt;code&gt;Mech.fields = {...}&lt;/code&gt; as well, I&#39;ve just been doing it this way since I started using Redux-ORM.  No practical difference as far as I know.)&lt;/p&gt;

&lt;p&gt;After making those changes, we&#39;re also going to be making several other related changes in a follow-up commit.  First, we need to add entries for MechDesigns and Mechs to our sample data.  Second, we need to update the existing Pilot data so that they refer to a specific individual mech&#39;s ID, rather than the ID of a mech type.  Those data changes look roughly like this (for one of the entries):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/3b25f24b5b7b74dd11d27d58134b11b35802a527&#34;&gt;Commit 3b25f24:Load Mechs and MechDesigns from sample data, and use in display&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/3b25f24b5b7b74dd11d27d58134b11b35802a527/src/data/sampleData.js&#34;&gt;features/data/sampleData.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;pilots : [
    {
        id : 1,
        name : &amp;quot;Natasha Kerensky&amp;quot;,
        rank : &amp;quot;Captain&amp;quot;,
        gunnery : 2,
        piloting : 2,
        age : 52,
-       mech : &amp;quot;WHM-6R&amp;quot;,
+       mech : 1,
    },
],
+designs : [
+   {
+       id : &amp;quot;WHM-6R&amp;quot;,
+       name : &amp;quot;Warhammer&amp;quot;,
+       weight : 70,
+   },
+],
+mechs : [
+   {
+       id : 1,
+       type : &amp;quot;WHM-6R&amp;quot;,
+       pilot : 1,
+   },
+]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Third, we need to update our &lt;code&gt;entities&lt;/code&gt; reducer to also load the Mech and Design entries into state:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/3b25f24b5b7b74dd11d27d58134b11b35802a527/src/app/reducers/entitiesReducer.js&#34;&gt;app/reducers/entitiesReducer&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;export function loadData(state, payload) {
    // Create a Redux-ORM session from our entities &amp;quot;tables&amp;quot;
    const session = schema.from(state);
    // Get a reference to the correct version of model classes for this Session
    const {Pilot, MechDesign, Mech} = session;

    const {pilots, designs, mechs} = payload;

    // Queue up creation commands for each entry
    pilots.forEach(pilot =&amp;gt; Pilot.parse(pilot));
    designs.forEach(design =&amp;gt; MechDesign.parse(design));
    mechs.forEach(mech =&amp;gt; Mech.parse(mech));

    // Apply the queued updates and return the updated &amp;quot;tables&amp;quot;
    return session.reduce();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The final change we need to make here is how we prepare the data in the &lt;code&gt;mapState&lt;/code&gt; function for &lt;code&gt;&amp;lt;Pilots&amp;gt;&lt;/code&gt;.  Previously, we just returned the plain JS objects directly.  Now, though, we need to follow the relations from Pilot to Mech to MechDesign in order to display what type of mech this Pilot uses.  The revised &lt;code&gt;mapState&lt;/code&gt; function now looks like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/3b25f24b5b7b74dd11d27d58134b11b35802a527/src/features/pilots/Pilots/Pilots.jsx&#34;&gt;features/pilots/Pilots/Pilots.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;const mapState = (state) =&amp;gt; {
    // Create a Redux-ORM Session from our &amp;quot;entities&amp;quot; slice, which
    // contains the &amp;quot;tables&amp;quot; for each model type
    const session = schema.from(state.entities);

    // Retrieve the model class that we need.  Each Session
    // specifically &amp;quot;binds&amp;quot; model classes to itself, so that
    // updates to model instances are applied to that session.
    // These &amp;quot;bound classes&amp;quot; are available as fields in the sesssion.
    const {Pilot} = session;

    // Query the session for all Pilot instances.
    // The QuerySet that is returned from all() can be used to
    // retrieve instances of the Pilot class, or retrieve the
    // plain JS objects that are actually in the store.

    // The withModels modifier will let us map over Model instances
    // for each entry, rather than the plain JS objects.
    const pilots = Pilot.all().withModels.map(pilotModel =&amp;gt; {
        // Access the underlying plain JS object using the &amp;quot;ref&amp;quot; field,
        // and make a shallow copy of it
        const pilot = {
            ...pilotModel.ref
        };
        
        // We want to look up pilotModel.mech.mechType.  Just in case the
        // relational fields are null, we&#39;ll do a couple safety checks as we go.

        // Look up the associated Mech instance using the foreign-key
        // field that we defined in the Pilot Model class
        const {mech} = pilotModel;

        // If there actually is an associated mech, include the
        // mech type&#39;s ID as a field in the data passed to the component
        if(mech &amp;amp;&amp;amp; mech.type) {
            pilot.mechType = mech.type.id;
        }

        return pilot;
    });

    // Now that we have an array of all pilot objects, return it as a prop
    return {pilots};
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With these changes in place, the &lt;code&gt;&amp;lt;PilotsList&amp;gt;&lt;/code&gt; should render exactly the same, but with the data for the last column now coming from the MechDesign &amp;quot;table&amp;quot; instead of being directly in each pilot entry.&lt;/p&gt;

&lt;h2 id=&#34;displaying-a-list-of-mechs&#34;&gt;Displaying a List of Mechs&lt;/h2&gt;

&lt;p&gt;We can now connect our &lt;code&gt;&amp;lt;Mechs&amp;gt;&lt;/code&gt; component the same way we did &lt;code&gt;&amp;lt;Pilots&amp;gt;&lt;/code&gt;.  This is pretty straightforward, and the only really interesting part is the &lt;code&gt;mapState&lt;/code&gt; method:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/7a5b7569a14195175e88d6959ae73c1c43b2c834&#34;&gt;Commit 7a5b756: Connect the Mechs component to display a list of mechs from the store&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/7a5b7569a14195175e88d6959ae73c1c43b2c834/src/features/mechs/Mechs/Mechs.jsx&#34;&gt;features/mechs/Mechs/Mechs.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;// Omit imports

const mapState = (state) =&amp;gt; {
    const session = schema.from(state.entities);
    const {Mech} = session;

    const mechs = Mech.all().withModels.map(mechModel =&amp;gt; {
        const mech = {
            // Copy the data from the plain JS object
            ...mechModel.ref,
            // Provide a default empty object for the relation
            mechType : {},
        };

        if(mechModel.type) {
            // Replace the default object with a copy of the relation&#39;s data
            mech.mechType = {...mechModel.type.ref};
        }

        return mech;
    });

    return {mechs}
}

// Omit component
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that gives us this update to our UI:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-12-practical-redux-part-5/mechs-list.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-12-practical-redux-part-5/mechs-list.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;h2 id=&#34;handling-selection-logic&#34;&gt;Handling Selection Logic&lt;/h2&gt;

&lt;p&gt;We&#39;re almost done with this set of changes.  The last thing to add for now is the ability for the user to click on either of the lists and select the item that was clicked on.  Right now, we&#39;re just defaulting to using the first item in an array as the &amp;quot;current&amp;quot; item for display in the Details sections.&lt;/p&gt;

&lt;p&gt;We&#39;ll start with the Pilots list.  We don&#39;t have a reducer for anything pilot-related yet, so we&#39;ll create one.  Going along with the idea of &amp;quot;normalization&amp;quot;, all we need to store is the ID of the currently selected pilot.  We&#39;ll actually get a bit fancy with the reducer logic, and handle de-selecting the current item entirely if the user clicks on it again:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/c42c5bdecc1469481089c2b83273930cb9bd2781&#34;&gt;Commit c42c5bd: Add logic for tracking the currently selected pilot&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/c42c5bdecc1469481089c2b83273930cb9bd2781/src/features/pilots/pilotsReducer.js&#34;&gt;features/pilots/pilotsReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {createReducer} from &amp;quot;common/utils/reducerUtils&amp;quot;;

import {PILOT_SELECT} from &amp;quot;./pilotsConstants&amp;quot;;

const initialState = {
    currentPilot : null
};

export function selectPilot(state, payload) {
    const prevSelectedPilot = state.currentPilot;
    const newSelectedPilot = payload.currentPilot;

    const isSamePilot = prevSelectedPilot === newSelectedPilot;
    
    return {
        // Deselect entirely if it&#39;s a second click on the same pilot,
        // otherwise go ahead and select the one that was clicked
        currentPilot : isSamePilot ? null : newSelectedPilot,
    };
}

export default createReducer(initialState, {
    [PILOT_SELECT] : selectPilot,
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That gives us some data handling, but we need to hook that up to the UI.  We need to pull the &lt;code&gt;currentPilot&lt;/code&gt; ID value into &lt;code&gt;&amp;lt;Pilots&amp;gt;&lt;/code&gt;, and use that in a couple places.  We should pass the actual entry for the current pilot into &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt;, and it would also be nice to highlight the row for that pilot in the list.  We also need to call the &lt;code&gt;selectPilot&lt;/code&gt; action creator with the ID of the pilot whose row was just clicked on.  Let&#39;s look at the relevant changes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/19c3c3a12ad99a01acf8bf6a62076caff8277a81&#34;&gt;Commit 19c3c3a: Implement selection handling for pilots&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/19c3c3a12ad99a01acf8bf6a62076caff8277a81/src/features/pilots/Pilots/Pilots.jsx&#34;&gt;features/pilots/Pilots/Pilots.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;// Omit initial imports

+import {selectPilot} from &amp;quot;../pilotsActions&amp;quot;;
+import {selectCurrentPilot} from &amp;quot;../pilotsSelectors&amp;quot;;

const mapState = (state) =&amp;gt; {}
    // Omit pilot objects lookup
    
+   const currentPilot = selectCurrentPilot(state);

    // Now that we have an array of all pilot objects, return it as a prop
-   return {pilots};
+   return {pilots, currentPilot};
}


+// Make an object full of action creators that can be passed to connect
+// and bound up, instead of writing a separate mapDispatch function
+const actions = {
+    selectPilot,
+};

export class Pilots extends Component { 
    render() {
-       const {pilots = []} = this.props;
+       const {pilots = [], selectPilot, currentPilot} = this.props;

-       const currentPilot = pilots[0] || {};
+       const currentPilotEntry = pilots.find(pilot =&amp;gt; pilot.id === currentPilot) || {}

        // Omit irrelevant layout component rendering for space
        return (
            &amp;lt;Segment&amp;gt;
-               &amp;lt;PilotsList pilots={pilots} /&amp;gt;
+               &amp;lt;PilotsList
+                   pilots={pilots}
+                   onPilotClicked={selectPilot}
+                   currentPilot={currentPilot}
+               /&amp;gt;
-               &amp;lt;PilotDetails pilot={currentPilot} /&amp;gt;
+               &amp;lt;PilotDetails pilot={currentPilotEntry} /&amp;gt;
            &amp;lt;/Segment&amp;gt;
        );
    }
}

-export default connect(mapState)(Pilots);
+export default connect(mapState, actions)(Pilots);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/19c3c3a12ad99a01acf8bf6a62076caff8277a81/src/features/pilots/PilotsList/PilotsList.jsx&#34;&gt;features/pilots/PilotsList/PilotsList.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;export default class PilotsList extends Component {
    render() {
-       const {pilots} = this.props;
+       const {pilots, onPilotClicked, currentPilot} = this.props;

        const pilotRows = pilots.map(pilot =&amp;gt; (
-           &amp;lt;PilotsListRow pilot={pilot} key={pilot.name}/&amp;gt;
+           &amp;lt;PilotsListRow
+               pilot={pilot}
+               key={pilot.name}
+               onPilotClicked={onPilotClicked}
+               selected={pilot.id === currentPilot}
+           /&amp;gt;
        ));

        // Omit layout rendering for space
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/19c3c3a12ad99a01acf8bf6a62076caff8277a81/src/features/pilots/PilotsList/PilotsListRow.jsx&#34;&gt;features/pilots/PilotsList/PilotsListRow.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;+import _ from &amp;quot;lodash&amp;quot;;

-const PilotsListRow = ({pilot={}}) =&amp;gt; {
+const PilotsListRow = ({pilot={}, onPilotClicked=_.noop, selected}) =&amp;gt; {
    const {
+        id = null,
        // Omit other fields
    } = pilot;
    
    return (
-       &amp;lt;Table.Row&amp;gt;
+       &amp;lt;Table.Row onClick={() =&amp;gt; onPilotClicked(id)} active={selected}&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And voila!  If we click on an entry in the pilots list, we should now see that row highlighted, and the entry also shown in the &lt;code&gt;&amp;lt;PilotDetails&amp;gt;&lt;/code&gt; form:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-12-practical-redux-part-5/pilots-list-selected.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-12-practical-redux-part-5/pilots-list-selected.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;And finally, after WAYYYY too long of a blog post, the last thing we&#39;ll do is implement the same behavior for the mechs list as well:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/54794acd672238117943aec309ab5ff75e5ceb7c&#34;&gt;Commit 54794ac: Add logic for tracking the currently selected mech&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/b461cb3276339f33bd5358e9c8ae046a6549a1f7&#34;&gt;Commit b461cb3: Implement selection handling for mechs&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And we see the same nicely highlighted selection for the mechs list:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-12-practical-redux-part-5/mechs-list-selected.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-12-practical-redux-part-5/mechs-list-selected.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;h2 id=&#34;final-thoughts&#34;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;For those of you who actually got this far, congratulations!  That was a lot of words, code, screenshots, and links.  But, &lt;strong&gt;&lt;em&gt;Project Mini-Mek&lt;/em&gt;&lt;/strong&gt; is now starting to look vaguely useful.  We&#39;ve got some realistic-looking data being loaded up, our first data models are defined, we&#39;re displaying that data in the UI, and we can actually interact with the lists a bit.  It&#39;s taken some time to get here, but we&#39;ve laid a pretty good foundation for the application.  After this, we should be able to start implementing some interesting and useful features with specific techniques.&lt;/p&gt;

&lt;p&gt;Be sure to tune in next time, when we &lt;em&gt;might&lt;/em&gt; just finally get around to doing some of that form editing work I&#39;ve been promising for the last couple posts! :)&lt;/p&gt;

&lt;h2 id=&#34;further-information&#34;&gt;Further Information&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek&#34;&gt;Project Mini-Mek repo&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/3&#34;&gt;PR #3: Practical Redux Part 5 - WIP branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/4&#34;&gt;PR #4: Practical Redux Part 5 - Final branch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Sourcemaps

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.html5rocks.com/en/tutorials/developertools/sourcemaps/&#34;&gt;An Introduction to Javascript Source Maps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://code.tutsplus.com/tutorials/source-maps-101--net-29173&#34;&gt;Source Maps 101&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://survivejs.com/webpack/developing-with-webpack/enabling-sourcemaps/&#34;&gt;SurviveJS Enabling Sourcemaps in Webpack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://lorefnon.me/2016/12/03/on-webpack-and-source-map-integration.html&#34;&gt;On Webpack and Source Map Integration: &lt;code&gt;devtool&lt;/code&gt; Options&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Create-React-App and Sourcemaps

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/facebookincubator/create-react-app/pull/924&#34;&gt;CRA PR #924: Enable sourcemaps in development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/facebookincubator/create-react-app/pull/1188&#34;&gt;CRA PR #1188: Update Webpack to fix source map issues&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Normalization

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/faq/OrganizingState.html#organizing-state-nested-data&#34;&gt;Redux FAQ: How do I organize nested or relational data in my state?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/recipes/StructuringReducers.html&#34;&gt;Redux docs: Structuring Reducers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    
    <item>
      <title>Practical Redux, Part 4: UI Layout and Project Structure</title>
      <link>https://blog.isquaredsoftware.com/2016/11/practical-redux-part-4-ui-layout-and-project-structure/</link>
      <pubDate>Tue, 22 Nov 2016 19:30:36 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2016/11/practical-redux-part-4-ui-layout-and-project-structure/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/2016/11/practical-redux-part-3-project-planning-and-setup/&#34;&gt;Last time&lt;/a&gt;&lt;/strong&gt;, we sketched out a feature list and some UI mockups for &lt;strong&gt;&lt;em&gt;Project Mini-Mek&lt;/em&gt;&lt;/strong&gt;, created a new project using Create-React-App, added a basic Redux configuration, and enabled the use of Hot Module Reloading so that we could see changes in our UI without having to reload the entire page.  In this part, &lt;strong&gt;we&#39;ll set up the initial application layout to match our UI mockups, talk about folder structures, and look at an example of managing UI state with Redux&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Before starting this series, I posted a poll on Twitter asking &lt;a href=&#34;https://twitter.com/acemarke/status/795390842890555393&#34;&gt;whether people would rather see &amp;quot;clean&amp;quot; commits, all WIP commits, or both&lt;/a&gt;.  The responses showed a preference for seeing &amp;quot;clean&amp;quot; commits, but I&#39;m actually going to include a way for people to see both.&lt;/p&gt;

&lt;p&gt;The code for this project is on Github at &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek&#34;&gt;github.com/markerikson/project-minimek&lt;/a&gt;&lt;/strong&gt;.  The original WIP commits I made for this post can be seen in &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/1&#34;&gt;PR #1: Practical Redux Part 4 WIP&lt;/a&gt;&lt;/strong&gt;, and the final &amp;quot;clean&amp;quot; commits can be seen in in &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/2&#34;&gt;PR #2: Practical Redux Part 4 Final&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&#34;table-of-contents&#34;&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#choosing-a-ui-toolkit&#34;&gt;Choosing a UI Toolkit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#setting-up-semantic-ui&#34;&gt;Setting Up Semantic-UI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#initial-ui-layout&#34;&gt;Initial UI Layout&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#building-a-tabbar-component&#34;&gt;Building a TabBar Component&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#rendering-tab-panels&#34;&gt;Rendering Tab Panels&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#thoughts-on-folder-structure&#34;&gt;Thoughts on Folder Structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#enabling-absolute-imports&#34;&gt;Enabling Absolute Imports&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#building-the-first-content-components&#34;&gt;Building the First Content Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#handling-tab-state-with-redux&#34;&gt;Handling Tab State with Redux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#filling-out-the-other-tabs&#34;&gt;Filling Out the Other Tabs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#final-thoughts&#34;&gt;Final Thoughts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#further-information&#34;&gt;Further Information&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;choosing-a-ui-toolkit&#34;&gt;Choosing a UI Toolkit&lt;/h2&gt;

&lt;p&gt;There&#39;s a seemingly infinite number of web UI toolkits and CSS frameworks out there, of which Bootstrap and its variations are probably the most popular.  I&#39;ve been using &lt;strong&gt;&lt;a href=&#34;http://semantic-ui.com/&#34;&gt;Semantic-UI&lt;/a&gt;&lt;/strong&gt; in another project, and been very happy with it.  It has a nice appearance out of the box, uses very readable markup, and allows considerable customization for theming, including several built-in theme options for various parts such as buttons.&lt;/p&gt;

&lt;p&gt;Semantic-UI consists of two main aspects: CSS-only content for styling, and logic for smarter widgets (such as AJAX fetching capabilities for the Dropdown component).  The original framework uses jQuery to implement its smart widgets.&lt;/p&gt;

&lt;p&gt;There are numerous React libraries that provide React components which render Semantic-UI markup.  However, many of them also try to wrap up the jQuery-based smart components as well.  In my own current app, I&#39;ve been trying to avoid dragging in jQuery as a dependency, so I spent some time looking for a React wrapper for Semantic-UI that avoided the jQuery parts.  I eventually found &lt;a href=&#34;https://github.com/shinzui/react-semantic-ui-kit&#34;&gt;React-Semantic-UI-Kit&lt;/a&gt;, which initially fit the bill.  However, since I started using it, there have been few updates to the wrappers, and there&#39;s some lingering pain points with the library (such as inability to override styles).&lt;/p&gt;

&lt;p&gt;One of the other React/Semantic-UI libraries I looked at was called &amp;quot;Stardust&amp;quot;.  It looked comprehensive and well written, but also wrapped up the jQuery components.  (There was some useful discussion about their approach in &lt;a href=&#34;https://www.reddit.com/r/reactjs/comments/4rpta0/any_feedback_on_stardust_semantic_ui_for_react/&#34;&gt;a Reddit thread about Stardust&lt;/a&gt;.) Since then, the situation has changed.  &amp;quot;Stardust&amp;quot; has been turned into the official &lt;strong&gt;&lt;a href=&#34;http://react.semantic-ui.com/introduction&#34;&gt;Semantic-UI-React&lt;/a&gt;&lt;/strong&gt; library, and now includes completely new React implementations for all of Semantic-UI&#39;s smart components, with no jQuery needed at all.  So, &lt;strong&gt;we&#39;ll be using Semantic-UI-React for the UI layout and styling&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It&#39;s important to note that Semantic-UI-React is only about generating the correct markup and adding additional logic on top.  In order for that markup to change any appearances, we need to include Semantic-UI&#39;s CSS.  Semantic-UI has &lt;a href=&#34;http://semantic-ui.com/introduction/build-tools.html&#34;&gt;its own build system&lt;/a&gt; that can be used to generate a customized theme, but to simplify things, we&#39;re just going to use the &lt;strong&gt;&lt;a href=&#34;https://github.com/Semantic-Org/Semantic-UI-CSS&#34;&gt;semantic-ui-css&lt;/a&gt;&lt;/strong&gt; package, which provides a prebuilt version of the full Semantic-UI CSS output.&lt;/p&gt;

&lt;h2 id=&#34;setting-up-semantic-ui&#34;&gt;Setting Up Semantic-UI&lt;/h2&gt;

&lt;p&gt;Our first step is to add &lt;code&gt;semantic-ui-react&lt;/code&gt; and &lt;code&gt;semantic-ui-css&lt;/code&gt; to our project;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;yarn add semantic-ui-react semantic-ui-css
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then, we need to import the main Semantic-UI CSS file into our code so it gets included in the bundle.  We should also render a single Semantic-UI &lt;code&gt;&amp;lt;Header&amp;gt;&lt;/code&gt; component to make sure that&#39;s working as intended.  While we&#39;re at it, let&#39;s yank out the sample component we set up, since we won&#39;t be needing it any more, and also do some cleanup on the original CSS and HTML that generated when the project was created (such as removing the spinning logo, and shrinking the size of the header bar).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/059c2a73be827ec90e870e9e55b8f5518b69a990&#34;&gt;Commit 059c2a7: Use Semantic-UI and clean up unused code&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/059c2a73be827ec90e870e9e55b8f5518b69a990/src/index.js&#34;&gt;index.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {Provider} from &amp;quot;react-redux&amp;quot;;

-import &#39;./index.css&#39;;
+import &amp;quot;semantic-ui-css/semantic.css&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/059c2a73be827ec90e870e9e55b8f5518b69a990/src/App.js&#34;&gt;App.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import React, { Component } from &#39;react&#39;;
import {
    Header,
} from &amp;quot;semantic-ui-react&amp;quot;;


import &#39;./App.css&#39;;

class App extends Component {
    render() {
        return (
            &amp;lt;div className=&amp;quot;App&amp;quot;&amp;gt;
                &amp;lt;div className=&amp;quot;App-header&amp;quot;&amp;gt;
                    &amp;lt;Header inverted as=&amp;quot;h1&amp;quot;&amp;gt;Project Mini-Mek&amp;lt;/Header&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        );
    }
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With the sample code cleaned up, our initial empty UI now looks like:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-4/pmm-semantic-header.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-4/pmm-semantic-header.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;Yay - a black bar with some white text!  Isn&#39;t this exciting? :)  Don&#39;t worry, we&#39;ll start adding a lot more from here.&lt;/p&gt;

&lt;h2 id=&#34;initial-ui-layout&#34;&gt;Initial UI Layout&lt;/h2&gt;

&lt;p&gt;Let&#39;s review the original mockup for &lt;strong&gt;&lt;em&gt;Project Mini-Mek&lt;/em&gt;&lt;/strong&gt;&#39;s UI:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-4/ui-mockup-unit-info.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-4/ui-mockup-unit-info.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;The main part of our layout is a tab bar with tabs for the four main panels.  Semantic-UI&#39;s &lt;code&gt;&amp;lt;Menu&amp;gt;&lt;/code&gt; component can be configured to display in a tabbed form, so we can go ahead and render an initial hardcoded version of our tabs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;.&#34;&gt;Commit 9bfab80: Render initial hardcoded tab bar&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/9bfab80acd5eaedeff5706569685fcb2da14cf00/src/App.js&#34;&gt;App.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {
    Header,
+   Container,
+   Menu,
} from &amp;quot;semantic-ui-react&amp;quot;;


class App extends Component {
    render() {
        return (
            &amp;lt;div className=&amp;quot;App&amp;quot;&amp;gt;
                &amp;lt;div className=&amp;quot;App-header&amp;quot;&amp;gt;
                    &amp;lt;Header inverted as=&amp;quot;h1&amp;quot;&amp;gt;Project Mini-Mek&amp;lt;/Header&amp;gt;
                &amp;lt;/div&amp;gt;
+               &amp;lt;Container&amp;gt;
+                   &amp;lt;Menu tabular size=&amp;quot;massive&amp;quot;&amp;gt;
+                       &amp;lt;Menu.Item name=&amp;quot;unitInfo&amp;quot; active={true}&amp;gt;Unit Info&amp;lt;/Menu.Item&amp;gt;
+                       &amp;lt;Menu.Item name=&amp;quot;pilots&amp;quot; active={false}&amp;gt;Pilots&amp;lt;/Menu.Item&amp;gt;
+                       &amp;lt;Menu.Item name=&amp;quot;mechs&amp;quot; active={false}&amp;gt;Mechs&amp;lt;/Menu.Item&amp;gt;
+                       &amp;lt;Menu.Item name=&amp;quot;unitOrganization&amp;quot; active={false}&amp;gt;Unit Organization&amp;lt;/Menu.Item&amp;gt;
+                   &amp;lt;/Menu&amp;gt;
+               &amp;lt;/Container&amp;gt;
            &amp;lt;/div&amp;gt;
        );
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That gives us the following result:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-4/pmm-tab-bar.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-4/pmm-tab-bar.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;Still not very exciting, but now we can start filling this out.&lt;/p&gt;

&lt;h2 id=&#34;building-a-tabbar-component&#34;&gt;Building a TabBar Component&lt;/h2&gt;

&lt;p&gt;We&#39;re going to need to track which tab is active, change that on click, and re-render the tab list.  We also will eventually need to swap which content panel is visible as well.  I added a &lt;code&gt;&amp;lt;TabBar&amp;gt;&lt;/code&gt; component that takes an array of tab names and labels and renders the tabs.  Now, we could have the &lt;code&gt;&amp;lt;TabBar&amp;gt;&lt;/code&gt; store the value of which tab is currently selected, but it&#39;s a good practice in React to write &lt;a href=&#34;https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0&#34;&gt;&amp;quot;container components&amp;quot;&lt;/a&gt; which store the state, and keep other components that are &amp;quot;presentational&amp;quot; and just display things based on the props they&#39;re given.  So, we&#39;ll create a &lt;code&gt;&amp;lt;TabBarContainer&amp;gt;&lt;/code&gt; component to track which tab is currently selected:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/c5600b7aabb82b2959785dc67613ae591ac45c97&#34;&gt;Commit c5600b7: Create a TabBar component to render a list of tabs&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/c5600b7aabb82b2959785dc67613ae591ac45c97/src/features/tabs/Tab.jsx&#34;&gt;features/tabs/Tab.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import React from &amp;quot;react&amp;quot;;
import {Menu} from &amp;quot;semantic-ui-react&amp;quot;;

const Tab = ({name, label, onClick, active}) =&amp;gt; (
    &amp;lt;Menu.Item
        name={name}
        content={label}
        active={active}
        onClick={() =&amp;gt; onClick(name)}
    /&amp;gt;
);

export default Tab;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/c5600b7aabb82b2959785dc67613ae591ac45c97/src/features/tabs/TabBar.jsx&#34;&gt;features/tabs/TabBar.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import React from &amp;quot;react&amp;quot;;
import {Menu} from &amp;quot;semantic-ui-react&amp;quot;;

import Tab from &amp;quot;./Tab&amp;quot;;

const TabBar = (props) =&amp;gt; {
    const {tabs, currentTab, onTabClick, ...otherProps} = props;

    const tabItems = tabs.map(tabInfo =&amp;gt; {
        const {name, label} = tabInfo;

        return (
            &amp;lt;Tab
                key={name}
                name={name}
                label={label}
                active={currentTab === name}
                onClick={onTabClick}
            /&amp;gt;
        );
    });

    return (
        &amp;lt;div&amp;gt;
            &amp;lt;Menu tabular attached=&amp;quot;top&amp;quot; {...otherProps}&amp;gt;
                {tabItems}
            &amp;lt;/Menu&amp;gt;
        &amp;lt;/div&amp;gt;
    )
}

export default TabBar;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/c5600b7aabb82b2959785dc67613ae591ac45c97/src/features/tabs/TabBarContainer.jsx&#34;&gt;features/tabs/TabBarContainer.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import React, {Component} from &amp;quot;react&amp;quot;;

import TabBar from &amp;quot;./TabBar&amp;quot;;

export default class TabBarContainer extends Component {
    constructor(props) {
        super(props);

        const {tabs = [{name : null}]} = props;

        const firstTab = tabs[0];

        this.state = {
            currentTab : firstTab.name
        } ;
    }

    onTabClick = (name) =&amp;gt; {
        this.setState({currentTab : name});
    }

    render() {
        const {tabs, ...otherProps} = this.props;
        const {currentTab} = this.state;
        
        return (
            &amp;lt;TabBar
                {...otherProps}
                currentTab={currentTab}
                onTabClick={this.onTabClick}
                tabs={tabs}
            /&amp;gt;
        )
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With that in place, we can then use it to render our main set of tabs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/47154d0cd195f5e565af7056ea99751b113a6694&#34;&gt;Commit 47154d0: Render the list of tabs using TabBarContainer&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/47154d0cd195f5e565af7056ea99751b113a6694/src/App.js&#34;&gt;App.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;class App extends Component {
    render() {
        const tabs = [
            {name : &amp;quot;unitInfo&amp;quot;, label : &amp;quot;Unit Info&amp;quot;},
            {name : &amp;quot;pilots&amp;quot;, label : &amp;quot;Pilots&amp;quot;},
            {name : &amp;quot;mechs&amp;quot;, label : &amp;quot;Mechs&amp;quot;},
            {name : &amp;quot;unitOrganization&amp;quot;, label : &amp;quot;Unit Organization&amp;quot;}
        ];

        return (
            &amp;lt;div className=&amp;quot;App&amp;quot;&amp;gt;
                &amp;lt;div className=&amp;quot;App-header&amp;quot;&amp;gt;
                    &amp;lt;Header inverted as=&amp;quot;h1&amp;quot;&amp;gt;Project Mini-Mek&amp;lt;/Header&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;Container&amp;gt;
                    &amp;lt;TabBarContainer tabs={tabs} size=&amp;quot;massive&amp;quot; /&amp;gt;
                &amp;lt;/Container&amp;gt;
            &amp;lt;/div&amp;gt;
        );
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;No major visual changes from this, but we can now click on each tab and see the &amp;quot;active&amp;quot; tab get highlighted.&lt;/p&gt;

&lt;h2 id=&#34;rendering-tab-panels&#34;&gt;Rendering Tab Panels&lt;/h2&gt;

&lt;p&gt;Right now the tab bar only shows the tabs themselves, but no content.  We really need to show a different component as the content for each tab, and swap which component is visible as the active tab changes.&lt;/p&gt;

&lt;p&gt;One way to do this would be to actually change which component is being rendered for the content panel each time the &lt;code&gt;currentTab&lt;/code&gt; prop changes.  Another would be to always render all the tabs, but toggle the visibility instead of un-rendering them.  We&#39;re going to go with toggling visibility, just because I feel like it.&lt;/p&gt;

&lt;p&gt;It&#39;s not too hard to write the logic for toggling the &lt;code&gt;display&lt;/code&gt; style on a given component, but I don&#39;t feel like writing that myself at the moment. There&#39;s a nice little utility component I&#39;ve found called &lt;a href=&#34;https://github.com/ccnokes/react-toggle-display&#34;&gt;React-Toggle-Display&lt;/a&gt; that just renders a span with your content, and toggles the visibility of the span based on a condition or flag prop.&lt;/p&gt;

&lt;p&gt;After adding that to the project, we need to update &lt;code&gt;TabBar&lt;/code&gt; to look for components in the tab definitions, and render those wrapped in a &lt;code&gt;&amp;lt;ToggleDisplay&amp;gt;&lt;/code&gt;.  We also need to add some initial dummy components to our existing tab definitions:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/21393edb923d0447bfeffa8c3ae1f89e1a1ff0be&#34;&gt;Commit 21393ed: Add ability to swap visible tab component based on active tab&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/21393edb923d0447bfeffa8c3ae1f89e1a1ff0be/src/features/tabs/TabBar.jsx&#34;&gt;features/tabs/TabBar.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import {Menu} from &amp;quot;semantic-ui-react&amp;quot;;
+import ToggleDisplay from &#39;react-toggle-display&#39;;


const TabBar = (props) =&amp;gt; {
    const {tabs, currentTab, onTabClick, ...otherProps} = props;

    const tabItems = tabs.map(tabInfo =&amp;gt; { /*.....*/ });

+   const tabPanels = tabs.map(tabInfo =&amp;gt; {
+       const {name, component : TabComponent} = tabInfo;

+       return (
+           &amp;lt;ToggleDisplay show={name === currentTab} key={name}&amp;gt;
+               &amp;lt;TabComponent /&amp;gt;
+           &amp;lt;/ToggleDisplay&amp;gt;
+       )
+   });

    return (
        &amp;lt;div&amp;gt;
            &amp;lt;Menu tabular attached=&amp;quot;top&amp;quot; {...otherProps}&amp;gt;
                {tabItems}
            &amp;lt;/Menu&amp;gt;
+
+            {tabPanels}
        &amp;lt;/div&amp;gt;
    );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/21393edb923d0447bfeffa8c3ae1f89e1a1ff0be/src/App.js&#34;&gt;App.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;
+const UnitInfo = () =&amp;gt; &amp;lt;div&amp;gt;Unit Info content&amp;lt;/div&amp;gt;;

+const Pilots = () =&amp;gt; &amp;lt;div&amp;gt;Pilots content&amp;lt;/div&amp;gt;;

+const Mechs = () =&amp;gt; &amp;lt;div&amp;gt;Mechs content&amp;lt;/div&amp;gt;;

+const UnitOrganization = () =&amp;gt; &amp;lt;div&amp;gt;Unit Organization content&amp;lt;/div&amp;gt;;

 class App extends Component {
     render() {
         const tabs = [
+           {name : &amp;quot;unitInfo&amp;quot;, label : &amp;quot;Unit Info&amp;quot;, component : UnitInfo,},
+           {name : &amp;quot;pilots&amp;quot;, label : &amp;quot;Pilots&amp;quot;, component : Pilots,},
+           {name : &amp;quot;mechs&amp;quot;, label : &amp;quot;Mechs&amp;quot;, component : Mechs,},
+           {name : &amp;quot;unitOrganization&amp;quot;, label : &amp;quot;Unit Organization&amp;quot;, component : UnitOrganization}
         ];
         
         // ....
     }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, as we click between tabs, we can see the visible panel change:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-4/pmm-tab-content.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-4/pmm-tab-content.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;Now that we&#39;ve got the tabs working, it&#39;s about time to start filling out the content for those tabs, and that means new components and new files.  But, we&#39;re going to take a detour first.  Creating new files means deciding where to put where to put them, and that&#39;s a topic in and of itself.&lt;/p&gt;

&lt;h2 id=&#34;thoughts-on-folder-structure&#34;&gt;Thoughts on Folder Structure&lt;/h2&gt;

&lt;p&gt;There&#39;s been lots of discussion over what constitutes a good folder structure for a Redux application.  The typical approaches generally fall into two categories: &amp;quot;file-type-first&amp;quot; (folders like &lt;code&gt;/reducers&lt;/code&gt;, &lt;code&gt;/components&lt;/code&gt;, etc), and &amp;quot;feature-first&amp;quot;, also sometimes referred to as &amp;quot;pods&amp;quot; or &amp;quot;domain-based&amp;quot; (folders that each have all the file types for a given feature).&lt;/p&gt;

&lt;p&gt;The original Redux examples use a &amp;quot;file-type-first&amp;quot; approach, but a lot of the recent articles and discussion have shown some convergence on the &amp;quot;feature-first&amp;quot; approach.  There&#39;s tradeoffs either way - &amp;quot;file-type-first&amp;quot; makes it really easy to do something like pulling together all the reducers, but the code for a given feature can be scattered around, and vice versa for &amp;quot;feature-first&amp;quot;.&lt;/p&gt;

&lt;p&gt;My own current approach is mostly a &amp;quot;feature-first&amp;quot;-style approach.  It&#39;s got some similarities to the approach described by Max Stoiber in his article &lt;a href=&#34;https://www.smashingmagazine.com/2016/09/how-to-scale-react-applications/&#34;&gt;How to Scale React Applications&lt;/a&gt;.  The main differences are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I prefer to give my files full unique names, rather than having files named &amp;quot;actions.js&amp;quot; and &amp;quot;reducer.js&amp;quot; in every folder.  This is mostly for ease of finding files and reading file names in editor tabs.  I also would rather give component files unique names, rather than naming them &lt;code&gt;SomeComponent/index.js&lt;/code&gt;.&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;I&#39;ve been using &lt;code&gt;index.js&lt;/code&gt; files to re-export functions and components upwards as a sort of &amp;quot;public API&amp;quot; for nested folders.&lt;/li&gt;
&lt;li&gt;I put these folders grouped under a folder named &lt;code&gt;features&lt;/code&gt;, rather than &lt;code&gt;containers&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;I personally tend to use thunks pretty heavily, only using sagas for some specific chunks of async logic.&lt;/li&gt;
&lt;li&gt;I also prefer to use &amp;quot;absolute imports&amp;quot;, such as &lt;code&gt;from &amp;quot;features/someFeature/SomeComponent&amp;quot;&lt;/code&gt;, rather than multi-level relative imports.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All that said, I&#39;m honestly not 100% happy with my current approach.  In particular, in a larger app I&#39;ve noticed that the time needed to hot-reload changes has gone up considerably, and I&#39;m not sure how much is due to just having more code, and how much is due to a more entangled dependency tree causing more files to be affected.  The proliferation of &lt;code&gt;index.js&lt;/code&gt; files and re-exports is also annoying.  So, I&#39;ll freely admit that I&#39;m still trying to figure things out myself.&lt;/p&gt;

&lt;p&gt;So, with those caveats, we&#39;re at a point where we should start extracting files to a more maintainable structure, but there&#39;s a couple tweaks we have to make first.&lt;/p&gt;

&lt;h2 id=&#34;enabling-absolute-imports&#34;&gt;Enabling Absolute Imports&lt;/h2&gt;

&lt;p&gt;As I mentioned, I prefer to consistently use import paths that start from the &lt;code&gt;src&lt;/code&gt; folder.  Among other things, that makes it easier to move files around, as compared to relative import paths.&lt;/p&gt;

&lt;p&gt;Normally, I&#39;d enable that by changing some path resolution options in my Webpack config, but since Create-React-App keeps all the configuration hidden, that&#39;s not an option unless we eject the project.  I did some digging around, and it turns out that, at least for now, there&#39;s a semi-undocumented way to enable this in a CRA app without having to eject.  If the &lt;code&gt;NODE_PATH&lt;/code&gt; environment variable is set, CRA/Webpack will use that in the resolution process.  Also, if a &lt;code&gt;.env&lt;/code&gt; file exists in the project root, those environment variables will be loaded up.  So, we can enable absolute imports by putting those two together.  However, the default &lt;code&gt;.gitignore&lt;/code&gt; file generated by CRA ignores &lt;code&gt;.env&lt;/code&gt;, so we&#39;ll need to fix that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/922292f02182740a5d496d5972439c506f58b7f5&#34;&gt;Commit 922292f: Enable absolute import paths (such as &amp;quot;features/a/SomeComponent&amp;quot;)&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/922292f02182740a5d496d5972439c506f58b7f5/.env&#34;&gt;.env&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;NODE_PATH=src
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/922292f02182740a5d496d5972439c506f58b7f5/.gitignore&#34;&gt;.gitignore&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;-.env
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With that, we can extract the dummy tab panel components into separate feature folders, and import them into App.js:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/07a9c688cb4eaee7aa1939064cd9ea730fc54b90&#34;&gt;Commit 07a9c68: Extract tab panels into separate feature folders&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/07a9c688cb4eaee7aa1939064cd9ea730fc54b90/src/App.js&#34;&gt;App.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;import TabBarContainer from &amp;quot;./components/TabBar&amp;quot;;
+import UnitInfo from &amp;quot;features/unitInfo/UnitInfo&amp;quot;;
+import Pilots from &amp;quot;features/pilots/Pilots&amp;quot;;
+import Mechs from &amp;quot;features/mechs/Mechs&amp;quot;;
+import UnitOrganization from &amp;quot;features/unitOrganization/UnitOrganization&amp;quot;;

import &#39;./App.css&#39;;

-const UnitInfo = () =&amp;gt; &amp;lt;div&amp;gt;Unit Info content&amp;lt;/div&amp;gt;;
-const Pilots = () =&amp;gt; &amp;lt;div&amp;gt;Pilots content&amp;lt;/div&amp;gt;;
-const Mechs = () =&amp;gt; &amp;lt;div&amp;gt;Mechs content&amp;lt;/div&amp;gt;;
-const UnitOrganization = () =&amp;gt; &amp;lt;div&amp;gt;Unit Organization content&amp;lt;/div&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;building-the-first-content-components&#34;&gt;Building The First Content Components&lt;/h2&gt;

&lt;h3 id=&#34;unit-info-tab&#34;&gt;Unit Info Tab&lt;/h3&gt;

&lt;p&gt;The first major piece of our UI will allow displaying and editing the details for whatever fictional Battletech combat group we&#39;ve created.  That includes things like what the name of the group is, what faction they work for, and so on.&lt;/p&gt;

&lt;p&gt;Per the &lt;a href=&#34;#initial-ui-layout&#34;&gt;mockup shown earlier&lt;/a&gt;, the Unit Info tab is just a basic form with a few fields.  We&#39;ll just add the &amp;quot;Name&amp;quot; and &amp;quot;Affiliation&amp;quot; fields for now, and deal with the other fields another time.&lt;/p&gt;

&lt;p&gt;Filling out the &lt;code&gt;&amp;lt;UnitInfo&amp;gt;&lt;/code&gt; component is pretty straightforward:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/7bcde0333b3213f451b288d49ec1b88e125f9a57&#34;&gt;Commit 7bcde03: Add initial form layout for UnitInfo&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/7bcde0333b3213f451b288d49ec1b88e125f9a57/src/features/unitInfo/UnitInfo/UnitInfo.jsx&#34;&gt;features/unitInfo/UnitInfo/UnitInfo.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import React from &amp;quot;react&amp;quot;;
import {
    Form,
    Dropdown,
    Segment
} from &amp;quot;semantic-ui-react&amp;quot;;

const FACTIONS = [
    // skip other entries
    {value : &amp;quot;lc&amp;quot;, text : &amp;quot;Lyran Commonwealth&amp;quot;},
    {value : &amp;quot;wd&amp;quot;, text : &amp;quot;Wolf&#39;s Dragoons&amp;quot;},
];

const UnitInfo = () =&amp;gt; {

    return (
        &amp;lt;Segment attached=&amp;quot;bottom&amp;quot;&amp;gt;
            &amp;lt;Form size=&amp;quot;large&amp;quot;&amp;gt;
                &amp;lt;Form.Field name=&amp;quot;name&amp;quot; width={6} &amp;gt;
                    &amp;lt;label&amp;gt;Unit Name&amp;lt;/label&amp;gt;
                    &amp;lt;input placeholder=&amp;quot;Name&amp;quot; value=&amp;quot;Black Widow Company&amp;quot;/&amp;gt;
                &amp;lt;/Form.Field&amp;gt;
                &amp;lt;Form.Field name=&amp;quot;affiliation&amp;quot; width={6}&amp;gt;
                    &amp;lt;label&amp;gt;Affiliation&amp;lt;/label&amp;gt;
                    &amp;lt;Dropdown
                       selection
                       options={FACTIONS}
                       value=&amp;quot;wd&amp;quot;
                    /&amp;gt;
                &amp;lt;/Form.Field&amp;gt;
            &amp;lt;/Form&amp;gt;
        &amp;lt;/Segment&amp;gt;
    );
}

export default UnitInfo;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now we finally have something slightly more visible to show off:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-4/pmm-unit-info-tab.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-4/pmm-unit-info-tab.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;h3 id=&#34;pilots-tab&#34;&gt;Pilots Tab&lt;/h3&gt;

&lt;p&gt;The second major part of the UI is a list of all the pilots that are part of our unit, and a section that will let us view and edit the details of the currently selected pilot.  I&#39;ll skip pasting in the entire Pilots tab component to save space, but here&#39;s the commit and the resulting UI:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/4f871f1684186ba6a0ca8a34d14f3fcd0b26eaf1&#34;&gt;Commit 4f871f1: Add initial Pilots tab layout with hardcoded content&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-4/pmm-pilots-tab.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-4/pmm-pilots-tab.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;h2 id=&#34;handling-tab-state-with-redux&#34;&gt;Handling Tab State with Redux&lt;/h2&gt;

&lt;p&gt;While working on the Pilots tab, a problem becomes noticeable: because the &amp;quot;current tab&amp;quot; value is stored as state in the &lt;code&gt;&amp;lt;TabBarContainer&amp;gt;&lt;/code&gt; component, reloading the component tree resets the selected tab when the component instance gets wiped out.  This is where Redux can help us, by moving our state outside the component tree.  Fortunately, because we kept the tab state in the &lt;code&gt;&amp;lt;TabBarContainer&amp;gt;&lt;/code&gt; component, we can replace the local component state version with one that pulls the value from Redux  instead.  The feature folder will contain the standard action constants, action creators, and reducers, as well as the selector functions to encapsulate looking up this piece of state.  For simplicity, we&#39;ll just look at the reducer and the new version of &lt;code&gt;&amp;lt;TabBarContainer&amp;gt;&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/e2312e28c36e9487def415562cd4d7bbe3807424&#34;&gt;Commit e2312e2: Rewrite tabs handling to be driven by Redux&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/e2312e28c36e9487def415562cd4d7bbe3807424/src/features/tabs/tabReducer.js&#34;&gt;features/tabs/tabReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import {createReducer} from &amp;quot;common/utils/reducerUtils&amp;quot;;

import {TAB_SELECTED} from &amp;quot;./tabConstants&amp;quot;;

const initialState = {
    currentTab : &amp;quot;unitInfo&amp;quot;,
};

export function selectTab(state, payload) {
    return {
        currentTab : payload.tabName,
    };
}

export default createReducer(initialState, {
    [TAB_SELECTED] : selectTab,
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/e2312e28c36e9487def415562cd4d7bbe3807424/src/features/tabs/TabBarContainer.jsx&#34;&gt;features/tabs/TabBarContainer.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import React, {Component} from &amp;quot;react&amp;quot;;
import {connect} from &amp;quot;react-redux&amp;quot;;

import TabBar from &amp;quot;common/components/TabBar&amp;quot;;

import {selectCurrentTab} from &amp;quot;./tabSelectors&amp;quot;;
import {selectTab} from &amp;quot;./tabActions&amp;quot;;

const mapState = (state) =&amp;gt; {
    const currentTab = selectCurrentTab(state);

    return {currentTab};
}

const actions = {onTabClick : selectTab};

export default connect(mapState, actions)(TabBar);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A couple things to note here.  We&#39;re using one of the umpteen million &lt;code&gt;createReducer&lt;/code&gt; utility functions out there, which lets you define separate reducer functions and a a lookup table instead of switch statements.  We&#39;re also using the object shorthand syntax that &lt;code&gt;connect&lt;/code&gt; supports for the &lt;code&gt;mapDispatch&lt;/code&gt; argument, allowing you to pass in an object full of action creator functions to be bound up, instead of writing an actual &lt;code&gt;mapDispatch&lt;/code&gt; function yourself.&lt;/p&gt;

&lt;h2 id=&#34;filling-out-the-other-tabs&#34;&gt;Filling Out the Other Tabs&lt;/h2&gt;

&lt;h3 id=&#34;mechs-tab&#34;&gt;Mechs Tab&lt;/h3&gt;

&lt;p&gt;With the tab state persisted, we can turn our attention back to laying out the other tabs.  The third major part of the UI is the Mechs tab.  This will basically be identical to the Pilots tab, in that it&#39;s a list of what Battlemechs our force owns, and some form of ability to view and edit details for a selected Battlemech.&lt;/p&gt;

&lt;p&gt;Again, the layout code is long enough that it&#39;s not worth pasting here in full, but here&#39;s what the resulting UI looks like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/f8f6fc459693e474d96e15d99ccfb79c0273cf9c&#34;&gt;Commit f8f6fc4: Add initial Mechs tab layout with hardcoded content&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-4/pmm-mechs-tab.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-4/pmm-mechs-tab.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;h3 id=&#34;unit-organization-tab&#34;&gt;Unit Organization Tab&lt;/h3&gt;

&lt;p&gt;The last major part of the UI is the Unit Table of Organization tab.  In Battletech fiction, Pilots and Mechs are grouped together into Lances of four Mechs apiece.  Three Lances are then grouped together to form a Company.  We&#39;re going to need some kind of treeview that will show the hierarchy of Company &amp;gt; Lance &amp;gt; Pilot+Mech, and eventually will need to be able to rearrange which Pilots are in which Lances.  For now, we&#39;ll just hardcode a tree-like display into the UI, and leave things alone until it&#39;s time to build the real thing:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/commit/e5f525845d489b47a9679d0aabdaa168bfcdd340&#34;&gt;Commit e5f5258: Add initial Unit Organization tab layout with hardcoded content&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-4/pmm-unit-org-tab.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-4/pmm-unit-org-tab.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;h2 id=&#34;final-thoughts&#34;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;That was a pretty good chunk of work.  We&#39;ve got all of our main UI laid out to match the mockups, started using a folder structure that should help the code stay maintainable as we move forward, and added some initial UI logic using Redux.  From here, we can start implementing some actual functionality, and that will give us a chance to look at some specific useful Redux techniques in the process.&lt;/p&gt;

&lt;p&gt;Next time, we&#39;ll look at some approaches for working with forms in Redux, and maybe actually get around to doing some data modeling as well.&lt;/p&gt;

&lt;h2 id=&#34;further-information&#34;&gt;Further Information&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek&#34;&gt;Project Mini-Mek repo&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/1&#34;&gt;PR #1: Practical Redux Part 4 - WIP branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/pull/2&#34;&gt;PR #2: Practical Redux Part 4 - Final branch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Semantic-UI

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://semantic-ui.com/&#34;&gt;Semantic-UI home&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://react.semantic-ui.com/&#34;&gt;Semantic-UI-React home&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/Semantic-Org/Semantic-UI-CSS&#34;&gt;Semantic-UI-CSS repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/ccnokes/react-toggle-display&#34;&gt;React-Toggle-Display&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Container/Presentational Components

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0&#34;&gt;Dan Abramov: Presentational and Container Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/react-redux-links/blob/master/react-component-patterns.md&#34;&gt;React/Redux Links: React Component Patterns&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Folder Structures

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/faq/CodeStructure.html#structure-file-structure&#34;&gt;Redux FAQ: Code Structure - What should my file structure look like?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.smashingmagazine.com/2016/09/how-to-scale-react-applications/&#34;&gt;Max Stoiber: How to Scale React Applications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/react-redux-links/blob/master/project-structure.md&#34;&gt;React/Redux Links: Project Structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/react-redux-links/blob/master/redux-architecture.md&#34;&gt;React/Redux Links: Redux Architecture&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Absolute imports in Create-React-App

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/facebookincubator/create-react-app/pull/476&#34;&gt;PR #476: Make Webpack use NODE_PATH variable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/facebookincubator/create-react-app/pull/693/files&#34;&gt;PR #693: Document existing workaround for absolute imports&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/facebookincubator/create-react-app/issues/741&#34;&gt;Issue #741: Support absolute paths with packages folder&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Selector Functions

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://medium.com/@adamrackis/querying-a-redux-store-37db8c7f3b0f&#34;&gt;Querying a Redux Store&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/react-redux-links/blob/master/redux-reducers-selectors.md#selectors-and-normalization&#34;&gt;React/Redux Links: Redux Reducers and Selectors&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    
    <item>
      <title>Practical Redux, Part 3: Project Planning and Setup</title>
      <link>https://blog.isquaredsoftware.com/2016/11/practical-redux-part-3-project-planning-and-setup/</link>
      <pubDate>Thu, 10 Nov 2016 23:00:00 -0400</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2016/11/practical-redux-part-3-project-planning-and-setup/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;h3 id=&#34;table-of-contents&#34;&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#planning-the-sample-application&#34;&gt;Planning the Sample Application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#ui-mockups&#34;&gt;UI Mockups&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#project-setup-and-configuration&#34;&gt;Project Setup and Configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#final-thoughts&#34;&gt;Final Thoughts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#further-information&#34;&gt;Further Information&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;planning-the-sample-application&#34;&gt;Planning The Sample Application&lt;/h2&gt;

&lt;p&gt;As I mentioned in the &lt;strong&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/2016/10/practical-redux-part-0-introduction/&#34;&gt;series introduction&lt;/a&gt;&lt;/strong&gt;, I&#39;ve got a number of specific techniques and concepts that I&#39;d like to talk about.  I&#39;ve had several requests to show some actual working examples of these techniques, so I&#39;ve decided to try to build a small example application to demonstrate these ideas in a meaningful context.&lt;/p&gt;

&lt;p&gt;I&#39;m a big fan of the &lt;a href=&#34;http://bg.battletech.com/&#34;&gt;Battletech game universe&lt;/a&gt;, a game about big stompy robots with weapons that are used to fight wars a thousand years in the future.  The game universe includes &lt;a href=&#34;http://bg.battletech.com/new-to-the-board-game/&#34;&gt;miniatures tabletop games, computer games, roleplaying games, fiction, and more&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There&#39;s a number of fan-built projects based in the Battletech universe.  One of the most popular is &lt;a href=&#34;http://megamek.org/about&#34;&gt;Megamek&lt;/a&gt;, a cross-platform computer implementation of the Classic Battletech tabletop game.  In addition, the Megamek authors have built a tool called &lt;strong&gt;&lt;a href=&#34;http://megamek.info/mekhq&#34;&gt;MekHQ&lt;/a&gt;&lt;/strong&gt;, a tool for managing an ongoing campaign for a fictional combat organization, such as a mercenary unit.&lt;/p&gt;

&lt;p&gt;For this blog series, &lt;strong&gt;I&#39;m planning to build a miniature version of the MekHQ application&lt;/strong&gt;.  I definitely do &lt;em&gt;not&lt;/em&gt; intend to seriously rebuild all of MekHQ&#39;s functionality, but it should serve as a useful inspiration and justification for most of the techniques I want to show off.&lt;/p&gt;

&lt;p&gt;On a related note: &lt;strong&gt;I&#39;m absolutely making this up as I go along :)&lt;/strong&gt;  I&#39;ve got some definite ideas for what I want to show off, but I&#39;ll be developing this sample app as I work on each post.  &lt;strong&gt;That means I&#39;ll probably make some mistakes, need to change things, and iterate on the code&lt;/strong&gt;.  This will be a learning experience for everyone involved :)&lt;/p&gt;

&lt;p&gt;Every project needs a good name.  I haven&#39;t come up with a good name yet, so we&#39;ll call this &lt;strong&gt;&lt;em&gt;&amp;quot;Project Mini-Mek&amp;quot;&lt;/em&gt;&lt;/strong&gt; for now.  (If anyone comes up with a better name, I&#39;m listening!)&lt;/p&gt;

&lt;h3 id=&#34;project-features&#34;&gt;Project Features&lt;/h3&gt;

&lt;p&gt;MekHQ is a very complex and in-depth application.  The &amp;quot;About&amp;quot; page describes it this way:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;MekHQ is a Java program that allow users to manage units in-between actual games of MegaMek. It implements most of the rules in the &amp;quot;Maintenance, Repair, and Salvage&amp;quot; section of Strategic Operations, many of the rules and options from the Mercenary Field Manual, and various options that allow users to customize a mercenary, house, or clan campaign to their liking . Some of the features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Track XP and improve pilot skills and abilities&lt;/li&gt;
&lt;li&gt;Integration with MegaMek and MegaMekLab&lt;/li&gt;
&lt;li&gt;Planetary map and the plotting of jumpship travel&lt;/li&gt;
&lt;li&gt;Organize a TO&amp;amp;E&lt;/li&gt;
&lt;li&gt;Create and resolve missions and scenarios&lt;/li&gt;
&lt;li&gt;Repair and salvage units&lt;/li&gt;
&lt;li&gt;Equipment tracking&lt;/li&gt;
&lt;li&gt;Financial tracking&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;For &lt;strong&gt;&lt;em&gt;Project Mini-Mek&lt;/em&gt;&lt;/strong&gt;, we&#39;re only going to deal with a couple of these, and at a very simple level.  Here&#39;s a tentative list of features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Load JSON data describing the pilots and Battlemechs in a combat force&lt;/li&gt;
&lt;li&gt;For both pilots and Battlemechs:

&lt;ul&gt;
&lt;li&gt;Show a list of all items&lt;/li&gt;
&lt;li&gt;Allow selection of an item in the list, and show details of the selected item&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Edit the details for a pilot&lt;/li&gt;
&lt;li&gt;Organize the pilots and their mechs into &amp;quot;lances&amp;quot; of four mechs, and the &amp;quot;lances&amp;quot; into a &amp;quot;company&amp;quot; of three lances.&lt;/li&gt;
&lt;li&gt;Add and remove pilots and mechs from the force&lt;/li&gt;
&lt;li&gt;Save the force back out to JSON&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, basically Yet Another CRUD APP, with some specific themes :)  For now, &lt;strong&gt;I&#39;m &lt;em&gt;not&lt;/em&gt; planning to deal with a backend or any AJAX handling&lt;/strong&gt;.  I figure I&#39;ll start with static JSON being directly imported, and then maybe add file import/export later on.&lt;/p&gt;

&lt;h3 id=&#34;ui-mockups&#34;&gt;UI Mockups&lt;/h3&gt;

&lt;h4 id=&#34;mekhq-pilot-listing&#34;&gt;MekHQ: Pilot Listing&lt;/h4&gt;

&lt;p&gt;Let&#39;s start by looking at some screenshots of the original MekHQ UI.  First, here&#39;s the screen that shows the list of pilots, and the details for the currently selected pilot:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-3/mekhq-pilot-list.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-3/mekhq-pilot-list.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;h4 id=&#34;mekhq-unit-table-of-organization-tree&#34;&gt;MekHQ: Unit Table of Organization Tree&lt;/h4&gt;

&lt;p&gt;Next, the &amp;quot;Unit Table of Organization&amp;quot; section, showing the various sub-units in a tree structure, and again with a details section on the right:&lt;/p&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-3/mekhq-unit-toe.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-3/mekhq-unit-toe.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;p&gt;This gives us a general idea of the UI layout we want: a tab bar across the top, with most of the tab panes containing a list of some kind on the left, and a details box for the currently selected item on the right.&lt;/p&gt;

&lt;p&gt;Here&#39;s some rough mockups of what our UI might look like:&lt;/p&gt;

&lt;h4 id=&#34;project-mini-mek-unit-info&#34;&gt;Project Mini-Mek: Unit Info&lt;/h4&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-3/ui-mockup-unit-info.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-3/ui-mockup-unit-info.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;h4 id=&#34;project-mini-mek-pilot-listing&#34;&gt;Project Mini-Mek: Pilot Listing&lt;/h4&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-3/ui-mockup-pilots.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-3/ui-mockup-pilots.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;h4 id=&#34;project-mini-mek-mech-listing&#34;&gt;Project Mini-Mek: Mech Listing&lt;/h4&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-3/ui-mockup-mechs.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-3/ui-mockup-mechs.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;h4 id=&#34;project-mini-mek-unit-table-of-organization-tree&#34;&gt;Project Mini-Mek: Unit Table of Organization Tree&lt;/h4&gt;


&lt;figure &gt;
    &lt;a href=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-3/ui-mockup-unit-toe.png&#34;&gt;
        &lt;img src=&#34;https://blog.isquaredsoftware.com/images/2016-11-practical-redux-part-3/ui-mockup-unit-toe.png&#34; /&gt;
    &lt;/a&gt;
    
&lt;/figure&gt;


&lt;h2 id=&#34;project-setup-and-configuration&#34;&gt;Project Setup and Configuration&lt;/h2&gt;

&lt;p&gt;We&#39;re going to set up the project using the excellent &lt;strong&gt;&lt;a href=&#34;https://github.com/facebookincubator/create-react-app&#34;&gt;Create-React-App&lt;/a&gt;&lt;/strong&gt; tool.  I&#39;m also going to be using the new &lt;strong&gt;&lt;a href=&#34;https://yarnpkg.com/&#34;&gt;Yarn&lt;/a&gt;&lt;/strong&gt; package manager, partly because it&#39;s supposed to be faster, and partly because this gives me a chance to try it out.  Also, as an FYI, I&#39;m writing all this on Windows, but I don&#39;t expect any meaningful OS/platform issues to pop up as we go.  Finally, &lt;strong&gt;I don&#39;t necessarily intend to show every last command I&#39;ve typed or bit of code I&#39;ve written as we go on&lt;/strong&gt; - the real focus is intended to be on using Redux itself, not using Git or an editor.&lt;/p&gt;

&lt;p&gt;The project is available on Github, at &lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek&#34;&gt;https://github.com/markerikson/project-minimek&lt;/a&gt;&lt;/strong&gt;.  I plan on updating it as I publish each post, and hope to show both some of the nitty-gritty &amp;quot;WIP&amp;quot; commits as well as cleaner &amp;quot;final result&amp;quot; commits.  Also, when I show code snippets or refer to source files in the repo, I&#39;ll usually try to link to that file on Github at the specific version where the changes were made.&lt;/p&gt;

&lt;p&gt;All right, let&#39;s do this!&lt;/p&gt;

&lt;h3 id=&#34;creating-the-project&#34;&gt;Creating the Project&lt;/h3&gt;

&lt;p&gt;Follow the instructions for installing the &lt;code&gt;create-react-app&lt;/code&gt; and &lt;code&gt;yarn&lt;/code&gt; tools on your system.  Once that&#39;s done, we can create our project:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;create-react-app project-minimek
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is a good time to initialize a Git repo for the initial sample files and project config files.  After the project is created, we want to set up a Yarn lockfile to nail down the specific dependency versions we&#39;re using.  &lt;code&gt;create-react-app&lt;/code&gt; already installed everything it needs (using NPM, although Yarn support is planned), but we need to run &lt;code&gt;yarn&lt;/code&gt; to make sure we&#39;re ready for adding more dependencies:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;cd project-minimek
yarn
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There&#39;s a bunch more file work done as Yarn figures out what dependencies you have, and prepares its lockfile, &lt;code&gt;yarn.lock&lt;/code&gt;.  That should be committed to Git as well.&lt;/p&gt;

&lt;h3 id=&#34;dependencies&#34;&gt;Dependencies&lt;/h3&gt;

&lt;p&gt;Time to pull in our initial list of dependencies.  Here&#39;s what we&#39;re going to add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Redux&lt;/strong&gt;: because without it, this would be a really short blog series&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;React-Redux&lt;/strong&gt;: ditto&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Redux-Thunk&lt;/strong&gt;: the most common and simple addon for side effects and complex dispatching logic&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reselect&lt;/strong&gt;: needed for memoized &amp;quot;selector&amp;quot; functions when retrieving data from our state&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Redux-ORM&lt;/strong&gt;: a handy abstraction layer for managing relational data in our state&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lodash&lt;/strong&gt;: every useful function you can think of, and a bunch more you didn&#39;t even know existed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;cuid&lt;/strong&gt;: We&#39;ll probably be generating IDs at some point, so this will fill that need&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can add them all in at once:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;yarn add redux react-redux redux-thunk reselect redux-orm lodash cuid
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then commit our &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;yarn.lock&lt;/code&gt; again.&lt;/p&gt;

&lt;h3 id=&#34;initial-redux-configuration&#34;&gt;Initial Redux Configuration&lt;/h3&gt;

&lt;p&gt;We need to set up the initial Redux store and reducers, make the store available to our component tree, and make sure that it&#39;s being used.  Here&#39;s what my initial Redux configuration looks like:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/455b1ee41e3968f622f3550dcaafbdebc245d6b9/src/store/configureStore.js&#34;&gt;store/configureStore.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {createStore, applyMiddleware, compose} from &amp;quot;redux&amp;quot;;

import thunk from &amp;quot;redux-thunk&amp;quot;;

import rootReducer from &amp;quot;../reducers/rootReducer&amp;quot;;

export default function configureStore(preloadedState) {
    const middlewares = [thunk];
    const middlewareEnhancer = applyMiddleware(...middlewares);

    const storeEnhancers = [middlewareEnhancer];
    
    const composedEnhancer = compose(...storeEnhancers);

    const store = createStore(
        rootReducer,
        preloadedState,
        composedEnhancer
    );

    return store;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I like to keep my store setup logic in a &lt;code&gt;configureStore&lt;/code&gt; function that can be further improved as time goes on.  I also try to keep the setup for each piece of the configuration process separate, so it&#39;s easy to follow what&#39;s going on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/455b1ee41e3968f622f3550dcaafbdebc245d6b9/src/reducers/testReducer.js&#34;&gt;reducers/testReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;const initialState = {
    data : 42
};

export default function testReducer(state = initialState, action) {
    return state;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/455b1ee41e3968f622f3550dcaafbdebc245d6b9/src/reducers/rootReducer.js&#34;&gt;reducers/rootReducer.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {combineReducers} from &amp;quot;redux&amp;quot;;

import testReducer from &amp;quot;./testReducer&amp;quot;;

const rootReducer = combineReducers({
    test : testReducer,
});

export default rootReducer;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Our initial reducers just pass along some test data so we can verify things are working.&lt;/p&gt;

&lt;p&gt;We then create a store instance and use it in the rendering process:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/455b1ee41e3968f622f3550dcaafbdebc245d6b9/src/index.js&#34;&gt;index.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import React from &#39;react&#39;;
import ReactDOM from &#39;react-dom&#39;;
import {Provider} from &amp;quot;react-redux&amp;quot;;

import App from &#39;./App&#39;;
import &#39;./index.css&#39;;

import configureStore from &amp;quot;./store/configureStore&amp;quot;;
const store = configureStore();

ReactDOM.render(
    &amp;lt;Provider store={store}&amp;gt;
        &amp;lt;App /&amp;gt;
    &amp;lt;/Provider&amp;gt;,
    document.getElementById(&#39;root&#39;)
);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, we add a simple test component, connect it to Redux, and render it in our App component to verify that everything&#39;s hooked up properly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/455b1ee41e3968f622f3550dcaafbdebc245d6b9/src/SampleComponent.jsx&#34;&gt;SampleComponent.jsx&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import React, {Component} from &amp;quot;react&amp;quot;;
import {connect} from &amp;quot;react-redux&amp;quot;;

const mapState = state =&amp;gt; ({
    data : state.test.data
});

class SampleComponent extends Component {
    render() {
        const {data} = this.props;
        
        return (
            &amp;lt;div&amp;gt;
                Data from Redux: {data}
            &amp;lt;/div&amp;gt;
        );
    }
}

export default connect(mapState)(SampleComponent);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/455b1ee41e3968f622f3550dcaafbdebc245d6b9/src/App.js&#34;&gt;App.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import React, { Component } from &#39;react&#39;;
import logo from &#39;./logo.svg&#39;;
import &#39;./App.css&#39;;

import SampleComponent from &amp;quot;./SampleComponent&amp;quot;;

class App extends Component {
    render() {
        return (
            &amp;lt;div className=&amp;quot;App&amp;quot;&amp;gt;
                &amp;lt;div className=&amp;quot;App-header&amp;quot;&amp;gt;
                    &amp;lt;img src={logo} className=&amp;quot;App-logo&amp;quot; alt=&amp;quot;logo&amp;quot;/&amp;gt;
                    &amp;lt;h2&amp;gt;Project Mini-Mek&amp;lt;/h2&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;SampleComponent /&amp;gt;
            &amp;lt;/div&amp;gt;
        );
    }
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We should now see the text &amp;quot;Data from Redux: 42&amp;quot; in our page, right below the header bar.&lt;/p&gt;

&lt;h3 id=&#34;adding-the-redux-devtools-extension&#34;&gt;Adding the Redux DevTools Extension&lt;/h3&gt;

&lt;p&gt;One of the original reasons for Redux&#39;s creation was the goal of &lt;strong&gt;&amp;quot;time-travel debugging&amp;quot;&lt;/strong&gt;: the ability to see the list of dispatched actions, view the contents of an action, see what parts of the state were changed after the action was dispatched,  view the overall application state after that dispatch, and step back and forth between dispatched actions.  Dan Abramov wrote the original &lt;a href=&#34;https://github.com/gaearon/redux-devtools&#34;&gt;Redux DevTools&lt;/a&gt; toolset, which showed that information with the UI as a component within the page.&lt;/p&gt;

&lt;p&gt;Since then, Mihail Diordiev has built the &lt;strong&gt;&lt;a href=&#34;https://github.com/zalmoxisus/redux-devtools-extension&#34;&gt;Redux DevTools Extension&lt;/a&gt;&lt;/strong&gt;, a browser extension that bundles together the core Redux DevTools logic and several community-built data visualizers as a browser extension, and adds a bunch of useful functionality on top of that.  Connecting the DevTools Extension to your store requires a few extra checks, so there&#39;s now a package available that encapsulates the process needed to hook up the DevTools Extension to your store.&lt;/p&gt;

&lt;p&gt;We&#39;ll add the helper package with &lt;code&gt;yarn add redux-devtools-extension&lt;/code&gt;, then make a couple small changes to the store setup logic:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/61899ca3b43bbb6a44f60520207663b20992d23d/src/store/configureStore.js&#34;&gt;store/configureStore.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-diff&#34;&gt;- import {createStore, applyMiddleware, compose} from &amp;quot;redux&amp;quot;;
+ import {createStore, applyMiddleware} from &amp;quot;redux&amp;quot;;
+ import { composeWithDevTools } from &#39;redux-devtools-extension/developmentOnly&#39;;


- const composedEnhancer = compose(...storeEnhancers);
+ const composedEnhancer = composeWithDevTools(...storeEnhancers);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This should add the DevTools enhancer to our store, but only when we&#39;re in development mode.  With that installed, the Redux DevTools browser extension can now view the contents of our store and the history of the dispatched actions.&lt;/p&gt;

&lt;h3 id=&#34;component-hot-reloading&#34;&gt;Component Hot Reloading&lt;/h3&gt;

&lt;p&gt;Out of the box, &lt;code&gt;create-react-app&lt;/code&gt; will watch your files on disk, and whenever you save changes, it will recompile the application and reload the entire page.  That&#39;s nice, but we can actually set up some improvements on that.  In particular, the Webpack build tool used by &lt;code&gt;create-react-app&lt;/code&gt; supports a feature known as &lt;strong&gt;&lt;a href=&#34;https://webpack.js.org/concepts/hot-module-replacement/&#34;&gt;Hot Module Replacement&lt;/a&gt;&lt;/strong&gt;, or HMR, which can hot-swap the newly compiled versions of files into your already-open application.  That lets us see our changes faster.  This works great with a React app, and even better in combination with Redux, since we can reload our component tree but still keep the same application state as before.&lt;/p&gt;

&lt;p&gt;We&#39;ll also want to add the &lt;code&gt;redbox-react&lt;/code&gt; package, which we can use to render an error message and a stack trace if something goes wrong.  Once that&#39;s installed, we need to update &lt;code&gt;index.js&lt;/code&gt; to rework the top-level rendering logic:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/ab7392198224f16e8149f12536e709dec284d173/src/index.js&#34;&gt;index.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jsx&#34;&gt;import React from &#39;react&#39;;
import ReactDOM from &#39;react-dom&#39;;
import {Provider} from &amp;quot;react-redux&amp;quot;;

import &#39;./index.css&#39;;

import configureStore from &amp;quot;./store/configureStore&amp;quot;;
const store = configureStore();

// Save a reference to the root element for reuse
const rootEl = document.getElementById(&amp;quot;root&amp;quot;);

// Create a reusable render method that we can call more than once
let render = () =&amp;gt; {
    // Dynamically import our main App component, and render it
    const App = require(&amp;quot;./App&amp;quot;).default;
    
    ReactDOM.render(
        &amp;lt;Provider store={store}&amp;gt;
            &amp;lt;App /&amp;gt;
        &amp;lt;/Provider&amp;gt;,
        rootEl
    );
};

if(module.hot) {
    // Support hot reloading of components
    // and display an overlay for runtime errors
    const renderApp = render;
    const renderError = (error) =&amp;gt; {
        const RedBox = require(&amp;quot;redbox-react&amp;quot;).default;
        ReactDOM.render(
            &amp;lt;RedBox error={error} /&amp;gt;,
            rootEl,
        );
    };

    // In development, we wrap the rendering function to catch errors,
    // and if something breaks, log the error and render it to the screen
    render = () =&amp;gt; {
        try {
            renderApp();
        }
        catch(error) {
            console.error(error);
            renderError(error);
        }
    };

    // Whenever the App component file or one of its dependencies
    // is changed, re-import the updated component and re-render it
    module.hot.accept(&amp;quot;./App&amp;quot;, () =&amp;gt; {
        setTimeout(render);
    });
}

render();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With this in place, editing one of our components (such as changing the text in &lt;code&gt;SampleComponent.jsx&lt;/code&gt;) should now just reload the component tree, rather than reloading the entire page.  If there&#39;s an error, we should see it displayed on the screen and logged in the console.  (To try it out, you can add &lt;code&gt;throw new Error(&amp;quot;Oops!&amp;quot;)&lt;/code&gt; to &lt;code&gt;SampleComponent.render()&lt;/code&gt; and see what happens.)&lt;/p&gt;

&lt;h3 id=&#34;reducer-hot-reloading&#34;&gt;Reducer Hot Reloading&lt;/h3&gt;

&lt;p&gt;Finally, we can also configure our project to hot-reload our reducers as well.  Right now, if we edit the initial state in our &lt;code&gt;testReducer.js&lt;/code&gt; from &lt;code&gt;data : 42&lt;/code&gt; to &lt;code&gt;data : 123&lt;/code&gt;, we&#39;ll see the whole page reload, just like it did for component edits before we added the hot reloading.  We need to listen for updates to the root reducer file, re-import it, and then replace the old reducer in the store with the new one.  The updated &lt;code&gt;configureStore.js&lt;/code&gt; looks like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek/blob/5f8ad093e4a856d0d32542226259524acfd7f22a/src/store/configureStore.js&#34;&gt;store/configureStore.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {createStore, applyMiddleware} from &amp;quot;redux&amp;quot;;
import { composeWithDevTools } from &#39;redux-devtools-extension/developmentOnly&#39;;

import thunk from &amp;quot;redux-thunk&amp;quot;;

import rootReducer from &amp;quot;../reducers/rootReducer&amp;quot;;

export default function configureStore(preloadedState) {
    const middlewares = [thunk];
    const middlewareEnhancer = applyMiddleware(...middlewares);

    const storeEnhancers = [middlewareEnhancer];
    
    const composedEnhancer = composeWithDevTools(...storeEnhancers);

    const store = createStore(
        rootReducer,
        preloadedState,
        composedEnhancer
    );

    if(process.env.NODE_ENV !== &amp;quot;production&amp;quot;) {
        if(module.hot) {
            module.hot.accept(&amp;quot;../reducers/rootReducer&amp;quot;, () =&amp;gt;{
                const newRootReducer = require(&amp;quot;../reducers/rootReducer&amp;quot;).default;
                store.replaceReducer(newRootReducer)
            });
        }
    }

    return store;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;final-thoughts&#34;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;At this point, we know what kind of app we want to build, and have a decent idea what it should do and what it should look like (or at least enough of an idea to get us started).  We also have an initial project set up with our basic dependencies, and some nice tweaks to the development workflow.&lt;/p&gt;

&lt;p&gt;Next time, we&#39;ll at setting up some initial UI layout, and possibly tackle some of the initial data modeling as well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you&#39;ve got questions, comments, or suggestions, please let me know!&lt;/strong&gt;  Leave me a comment here, file an issue in the repo, or ping me on Twitter or Reactiflux.&lt;/p&gt;

&lt;h2 id=&#34;further-information&#34;&gt;Further Information&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/project-minimek&#34;&gt;Project Mini-Mek repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/facebookincubator/create-react-app&#34;&gt;Create-React-App home&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Time travel debugging:

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=xsSnOQynTHs&#34;&gt;Dan Abramov&#39;s original &amp;quot;Hot Reloading with Time Travel talk&amp;quot;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/gaearon/redux-devtools&#34;&gt;Redux DevTools repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/zalmoxisus/redux-devtools-extension&#34;&gt;Redux DevTools Extension repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/react-redux-links/blob/master/redux-techniques.md#debugging&#34;&gt;React/Redux Links: Redux Techniques - Debugging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/redux-ecosystem-links/blob/master/devtools.md&#34;&gt;Redux Addons Catalog: Dev Tools&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Webpack Hot Module Replacement info

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://webpack.js.org/concepts/hot-module-replacement/&#34;&gt;Webpack docs: Concepts - Hot Module Replacement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://webpack.js.org/guides/hot-module-replacement/&#34;&gt;Webpack docs: Guides - Hot Module Replacement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://medium.com/@rajaraodv/webpack-hot-module-replacement-hmr-e756a726a07&#34;&gt;Webpack HMR: How It Works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ctheu.com/2015/12/29/webpack-hot-reloading-and-react-how/&#34;&gt;Webpack Hot Reloading and React&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/markerikson/react-redux-links/blob/master/webpack-advanced-techniques.md#hot-module-replacement&#34;&gt;React/Redux Links: Webpack Advanced Techniques - HMR&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    
    <item>
      <title>Practical Redux, Part 2: Redux-ORM Concepts and Techniques</title>
      <link>https://blog.isquaredsoftware.com/2016/10/practical-redux-part-2-redux-orm-concepts-and-techniques/</link>
      <pubDate>Mon, 31 Oct 2016 23:30:00 -0400</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2016/10/practical-redux-part-2-redux-orm-concepts-and-techniques/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;h3 id=&#34;intro&#34;&gt;Intro&lt;/h3&gt;

&lt;p&gt;Continuing on from the previous post about what Redux-ORM is and why you might want to use it, let&#39;s look at the &lt;strong&gt;core concepts of Redux-ORM, and how I actually use it in my own application&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The code examples in this post are intended to demonstrate the general concepts and workflow, and probably won&#39;t entirely run as-is. &lt;strong&gt;See the &lt;a href=&#34;https://blog.isquaredsoftware.com/2016/10/practical-redux-part-0-introduction/&#34;&gt;series introduction&lt;/a&gt;&lt;/strong&gt; for info on the example scenarios and plans for demonstrating these ideas in a working example application later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: These two posts cover use of Redux-ORM 0.8, but version 0.9 has since been released with several breaking API changes.  The basic usage is still the same, but some aspects of behavior are different.  See &lt;strong&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/2017/07/practical-redux-part-9-managing-dependencies/&#34;&gt;Practical Redux, Part 9: Upgrading Redux-ORM&lt;/a&gt;&lt;/strong&gt; for details on the differences.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&#34;table-of-contents&#34;&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#redux-orm-core-concepts&#34;&gt;Redux-ORM Core Concepts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#typical-usage&#34;&gt;Typical Usage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#adding-specialized-behavior&#34;&gt;Adding Specialized Behavior&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#final-thoughts&#34;&gt;Final Thoughts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;redux-orm-core-concepts&#34;&gt;Redux-ORM Core Concepts&lt;/h2&gt;

&lt;p&gt;Redux-ORM serves as an extremely useful abstraction layer over the normalized data in your Redux store.  There&#39;s a number of key concepts to understand when using it:&lt;/p&gt;

&lt;h3 id=&#34;sessions&#34;&gt;Sessions&lt;/h3&gt;

&lt;p&gt;The Session class is used to interact with an underlying set of data.  If you use the reducer generated by &lt;code&gt;schema.reducer()&lt;/code&gt;, Redux-ORM will create a Session instance internally.  Otherwise, you can create Session instances by calling &lt;code&gt;schema.from(entities)&lt;/code&gt; (which creates a Session that will apply updates immutably), or &lt;code&gt;schema.withMutations(entities)&lt;/code&gt; (which creates a Session that will directly mutate the provided data).&lt;/p&gt;

&lt;p&gt;When a Session instance is created from source data, Redux-ORM creates temporary subclasses of the Model types available in the Schema, &amp;quot;binds&amp;quot; them to that session, and exposes the subclasses as fields on the Session instance.  This means &lt;strong&gt;it&#39;s important that you always extract the Model classes you want to use from the Session instance and interact with those&lt;/strong&gt;, rather than using the versions you might have directly imported at the module level.  If you&#39;re writing your reducers as part of your Model classes, Redux-ORM passes the bound version of the current class in as the third argument, and the current Session instance as the fourth argument.&lt;/p&gt;

&lt;h3 id=&#34;models&#34;&gt;Models&lt;/h3&gt;

&lt;p&gt;The Model instances returned by a Session really just &lt;strong&gt;act as facades over the plain Javascript objects inside the store&lt;/strong&gt;.  When a Model instance is requested, Redux-ORM generates property fields on the Model instances based on the keys in the underlying object, as well as the declared relations.  These property fields define getters and setters that encapsulate the real behavior.  Depending on what that field is, the getters will return the plain value from the underlying object, a new Model instance for a single relation, or a QuerySet instance for a collection relation.  The underlying object can be accessed directly using &lt;code&gt;someModelInstance.ref&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The use of properties and getters also means that &lt;strong&gt;relations are not denormalized until you actually access those properties&lt;/strong&gt;.  So, even an entity has a lot of relations, there shouldn&#39;t be any additional expense to just retrieving a Model instance for that entity.&lt;/p&gt;

&lt;h3 id=&#34;updates&#34;&gt;Updates&lt;/h3&gt;

&lt;p&gt;Internally, Redux-ORM uses a queue of actions, and applies those actions kind of like a mini-Redux (where each action is used to update its internal state reducer-style).  For example, running &lt;code&gt;const pilot = Pilot.create(attributes); pilot.name = &amp;quot;Jaime Wolf&amp;quot;;&lt;/code&gt; would queue up a &lt;code&gt;CREATE&lt;/code&gt; action and an &lt;code&gt;UPDATE&lt;/code&gt; action.  &lt;strong&gt;Neither of those actions is applied until you call one of the appropriate methods on the session or model&lt;/strong&gt;, such as &lt;code&gt;session.reduce()&lt;/code&gt;.  There is one exception to this: if the session was created using &lt;code&gt;schema.withMutations(entities)&lt;/code&gt;, it &lt;em&gt;will&lt;/em&gt; directly apply all updates to the affected object right away.  Otherwise, &lt;strong&gt;all updates are queued up, then applied immutably in sequence to produce the final result&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&#34;managing-relations&#34;&gt;Managing Relations&lt;/h3&gt;

&lt;p&gt;Redux-ORM relies on a &amp;quot;QuerySet&amp;quot; class as an abstraction for managing collections.  A QuerySet knows what Model type it relates to, and contains a list of IDs.  Operations such as &lt;code&gt;filter()&lt;/code&gt; return a new QuerySet instance with a different internal list of IDs.  QuerySets have an internal flag indicating whether they should dereference just the plain objects, or corresponding Model instances.  This is used by chaining the properties &lt;code&gt;withModels&lt;/code&gt; or &lt;code&gt;withRefs&lt;/code&gt; into the lookup process, such as &lt;code&gt;this.mechs.withModels.map(mechModel =&amp;gt; mechModel.name)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;many&lt;/code&gt;-type relations, Redux-ORM will auto-generate &amp;quot;through model&amp;quot; classes, which store the IDs for both items in the relation.  For example, a &lt;code&gt;Lance&lt;/code&gt; with a field &lt;code&gt;pilots : many(&amp;quot;Pilot&amp;quot;)&lt;/code&gt; would result in a &lt;code&gt;LancePilot&lt;/code&gt; class and table.  There&#39;s a PR currently open to allow customization of those through models, to better enable situations like ordering of items in that relation.&lt;/p&gt;

&lt;h3 id=&#34;synchronization&#34;&gt;Synchronization&lt;/h3&gt;

&lt;p&gt;It&#39;s also important to understand that Redux-ORM &lt;strong&gt;&lt;em&gt;does not&lt;/em&gt;&lt;/strong&gt; include any capabilities for synchronizing data with a server (such as the methods included with Backbone.Model or Ember Data).  It is &lt;em&gt;only&lt;/em&gt; about managing relations stored locally as plain JS data.  (In fact, despite the name, it doesn&#39;t even depend on Redux at all.)  You are responsible for handling data syncing yourself.&lt;/p&gt;

&lt;h2 id=&#34;typical-usage&#34;&gt;Typical Usage&lt;/h2&gt;

&lt;p&gt;I primarily use Redux-ORM as a specialized &amp;quot;super-selector&amp;quot; and &amp;quot;super-immutable-update&amp;quot; tool.  This means that I work with it in my selector functions, thunks, reducers, and &lt;code&gt;mapState&lt;/code&gt; functions.  Here&#39;s some of the practices I&#39;ve come up with.&lt;/p&gt;

&lt;h3 id=&#34;entity-selection&#34;&gt;Entity Selection&lt;/h3&gt;

&lt;p&gt;Because I consistently use the Schema singleton instance across my application, I&#39;ve created a selector that encapsulates extracting the current &lt;code&gt;entities&lt;/code&gt; slice and returning a Session instance initialized with that data:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {createSelector} from &amp;quot;reselect&amp;quot;;
import schema from &amp;quot;./schema&amp;quot;;

export const selectEntities = state =&amp;gt; state.entities;

export const getEntitiesSession = createSelector(
    selectEntities,
    entities =&amp;gt; schema.from(entities),
);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using that selector, I can retrieve a Session instance inside of a &lt;code&gt;mapState&lt;/code&gt; function, and look up pieces of data as needed by that component.&lt;/p&gt;

&lt;p&gt;This has a couple benefits.  In particular, because many different &lt;code&gt;mapState&lt;/code&gt; functions might be trying to do data lookups right in a row, only one Session instance should be created per store update, so this should be something of a performance optimization.  Redux-ORM does offer a &lt;code&gt;schema.createSelector()&lt;/code&gt; function that is supposed to create optimized selectors that track which models were accessed, but I haven&#39;t yet gotten around to actually trying that.  I may look into it later when I do some perf/optimization passes on my own application.&lt;/p&gt;

&lt;p&gt;Overall, I make it a point to keep all my components unaware of Redux-ORM&#39;s existence, and only pass plain data as props to my components.&lt;/p&gt;

&lt;h3 id=&#34;writing-entity-based-reducers&#34;&gt;Writing Entity-Based Reducers&lt;/h3&gt;

&lt;p&gt;Most of my entity-related reducers are based more around a specific action case rather than a certain Model class.  Because of this, some of my reducers are fairly generic, and take an item type and an item ID as parameters in the action payload.  As an example, here&#39;s a generic reducer for updating the attributes of any arbitrary Model instance:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;export function updateEntity(state, payload) {
    const {itemType, itemID, newItemAttributes} = payload;

    const session = schema.from(state);
    const ModelClass = session[itemType];

    let newState = state;

    if(ModelClass.hasId(itemID)) {
        const modelInstance = ModelClass.withId(itemID);

        modelInstance.update(newItemAttributes);

        newState = session.reduce();
    }

    return newState;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Not all my reducers are this generic - some of them do end up specifically referencing certain model types in specific ways.  In some cases, I can build up higher-level functionality by reusing these generic building block reducers.&lt;/p&gt;

&lt;p&gt;My reducers generally follow the same pattern: extract parameters from payload, create Session instance, queue updates, apply updates using &lt;code&gt;session.reduce()&lt;/code&gt;, and return the new state.  There&#39;s admittedly some verbosity there, which I could probably abstract out a bit more if I wanted to, but the overall consistency and the simplification of the actual update logic is a big win in my book.&lt;/p&gt;

&lt;p&gt;I&#39;ve also written a couple small utilities that aid with the process of looking up a given model by its type and ID:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;export function getModelByType(session, itemType, itemID) {
    const modelClass = session[itemType];
    const model = modelClass.withId(itemID);
    return model;
}

export function getModelIdentifiers(model) {
    return {
        itemID : model.getId(),
        itemType : model.getClass().modelName,
    };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Many of my actions contain &lt;code&gt;itemType&lt;/code&gt; and &lt;code&gt;itemID&lt;/code&gt; pairs in their payloads.  Part of that is that I personally lean towards keeping my actions fairly minimal, with more work in the thunks &lt;em&gt;and&lt;/em&gt; the reducers as necessary, and don&#39;t like blindly merging data from an action straight into my state.&lt;/p&gt;

&lt;h3 id=&#34;handling-iterative-updates&#34;&gt;Handling Iterative Updates&lt;/h3&gt;

&lt;p&gt;I&#39;ve found that I frequently need to apply updates in a multi-step fashion.  However, because the Model instances are facades over the plain data, this doesn&#39;t always work well.  If I&#39;ve queued up some update (such as &lt;code&gt;someModel.someField = 123&lt;/code&gt;), that change isn&#39;t really &amp;quot;visible&amp;quot; to the Model instances until it&#39;s been applied.  Since updates are applied immutably, this situation can get complicated.&lt;/p&gt;

&lt;p&gt;One way to handle this might be to create an initial Session instance with the starting data, then create a second Session instance with the updated data:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;const firstSession = schema.from(entities);
const {Pilot} = firstSession;

const pilot = Pilot.withId(pilotId);
// Attribute update queued up here
pilot.name = &amp;quot;Natasha Kerensky&amp;quot;;

const updatedEntities = firstSession.reduce();

const secondSession = schema.from(updatedEntities);
const {Pilot : Pilot2} = secondSession;

// do something with the classes from the second session, which
// are now acting as facades over the updated data object
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&#39;m not a fan of that approach, though.  It&#39;s kind of ugly, and there could be confusion over which Session and Model classes I need to use at any moment.&lt;/p&gt;

&lt;p&gt;I did some digging through the Redux-ORM source, and noted that a Session instance ultimately is a wrapper around the object stored as &lt;code&gt;this.state&lt;/code&gt; internally.  Since that field is public, we can interact with it.  In particular, I realized that I could take an existing Session instance and update it to reference a new state object, without having to create a second Session instance:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;const session = schema.from(entities);
const {Pilot} = session;

const pilot = Pilot.withId(pilotId);
pilot.name = &amp;quot;Natasha Kerensky&amp;quot;;

// Immutably apply updates, then point the session at the updated state object.
session.state = session.reduce();

// All field/model lookups now use the updated state object
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This approach has allowed me to implement some fairly complex multi-step data updates, while still handling all the data in an immutable fashion.&lt;/p&gt;

&lt;p&gt;Since this process does actually modify the current Session instance, I make it a point to never do this with the &amp;quot;shared&amp;quot; Session instance returned from my &lt;code&gt;getEntitiesSession()&lt;/code&gt; selector.  If I&#39;m doing this in a reducer, I always create a new Session anyway.  If I&#39;m doing this in a thunk, I use a second selector to create a separate session instance for this task:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;export function getUnsharedEntitiesSession(state) {
    const entities = selectEntities(state);
    return schema.from(entities);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;adding-specialized-behavior&#34;&gt;Adding Specialized Behavior&lt;/h2&gt;

&lt;p&gt;Redux-ORM provides some very useful tools for dealing with normalized data, but it only has so much functionality built-in.  Fortunately, it also serves as a great starting point for building additional functionality.&lt;/p&gt;

&lt;h3 id=&#34;serializing-and-deserializing-data&#34;&gt;Serializing and Deserializing Data&lt;/h3&gt;

&lt;p&gt;As mentioned in the previous post, the Normalizr library is the de-facto standard for normalizing data received from the server.  I&#39;ve found that Redux-ORM can be used to mostly build a replacement for Normalizr.  I added static &lt;code&gt;parse()&lt;/code&gt; methods to each of my classes, which know how to handle the incoming data based on the relations:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;class Lance extends Model {
    static parse(lanceData) {
        // Because it&#39;s a static method, &amp;quot;this&amp;quot; refers to the class itself.
        // In this case, we&#39;re running inside a subclass bound to the Session.
        const {Pilot, Battlemech, Officer} = this.session;
        
        // Assume our incoming data looks like:
        // {name, commander : {}, mechs : [], pilots : []}
        
        let clonedData = {
           ...lanceData,
           commander = Officer.parse(clonedData.commander),
           mechs : lanceData.mechs.map(mech =&amp;gt; Battlemech.parse(mech)),
           pilots : lanceData.pilots.map(pilot =&amp;gt; Pilot.parse(pilot))
        };
        
        return this.create(clonedData);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This method could then be called in either a thunk or a reducer to help process data from a response, and queue up the necessary &lt;code&gt;CREATE&lt;/code&gt; actions inside of Redux-ORM.  If called in a reducer, the updates could be applied directly to the existing state.  If used in a thunk, you&#39;d want to take the resulting normalized data and include it in a dispatched action for merging into the store.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: My own data is just nested, with no duplication.  I had originally assumed that this process would handle duplicate data okay, by merging it together or something similar.  However, some testing has shown that assumption was wrong.  If an item with an ID already actually exists in the state, and a &lt;code&gt;CREATE&lt;/code&gt; action with the same type and ID is queued, Redux-ORM will throw an error.  If two &lt;code&gt;CREATE&lt;/code&gt; actions with the same ID are queued up together, Redux-ORM will effectively throw away the first created entry and replace it with the second created entry.  I&#39;ve &lt;a href=&#34;https://github.com/tommikaikkonen/redux-orm/issues/50&#34;&gt;opened up an issue&lt;/a&gt; to discuss what the desired behavior should be.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;On the flip side, it&#39;s often necessary to send a denormalized version of the data back to the server.  I&#39;ve added &lt;code&gt;toJSON()&lt;/code&gt; methods to my models to support that:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;class Lance extends Model {
    toJSON() {
        const data = {
            // Include all fields from the plain data object
            ...this.ref,
            // As well as serialized versions of all the relations we know about
            commander : this.commander.toJSON(),
            pilots : this.pilots.withModels.map(pilot =&amp;gt; pilot.toJSON()),
            mechs : this.mechs.withModels.map(mech =&amp;gt; mech.toJSON())
        };
        
        return data;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;creation-and-deletion&#34;&gt;Creation and Deletion&lt;/h3&gt;

&lt;p&gt;I often need to generate initial data for a new entity in an action creator before either sending it to the server or adding it to the store.  I&#39;m still waffling somewhat on what exactly is the best way to approach this.  For now, I&#39;ve added &lt;code&gt;generate&lt;/code&gt; methods that can help encapsulate the process:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;const defaultAttributes = {
    name : &amp;quot;Unnamed Lance&amp;quot;,
};

class Lance extends Model {
    static generate(specifiedAttributes = {}) {
        const id = generateUUID(&amp;quot;lance&amp;quot;);
        
        const mergedAttributes = {
            ...defaultAttributes,
            id,
            ...specifiedAttributes,     
        }
        
        return this.create(mergedAttributes);
    }
}

function createNewLance(name) {
    return (dispatch, getState) =&amp;gt; {
        const session = getUnsharedEntitiesSession(getState());
        const {Lance} = session;
        
        const newLance = Lance.generate({name : &amp;quot;Command Lance&amp;quot;});
        session.state = session.reduce();
        const itemAttributes = newLance.toJSON();
        
        dispatch(createEntity(&amp;quot;Lance&amp;quot;, newLance.getId(), itemAttributes));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Meanwhile, Redux-ORM&#39;s &lt;code&gt;Model.delete&lt;/code&gt; method doesn&#39;t fully cascade, so I&#39;ve implemented a custom &lt;code&gt;deleteCascade&lt;/code&gt; method where neded:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;class Lance extends Model {
    deleteCascade() {
        this.mechs.withModels.forEach(mechModel =&amp;gt; mechModel.deleteCascade());
        this.pilots.withModels.forEach(pilotModel =&amp;gt; pilotModel.deleteCascade());
        this.delete();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&#39;ve also implemented a number of additions to better handle copying data back and forth between various versions of a model instance (such as a &amp;quot;current&amp;quot; version vs a &amp;quot;WIP draft&amp;quot; version), which I&#39;ll discuss in a later post on data editing approaches.&lt;/p&gt;

&lt;h2 id=&#34;final-thoughts&#34;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;Redux-ORM does introduce some additional concepts on top of Redux.  Like any abstraction layer, it can be leaky at times, and you do need to understand what&#39;s going on at the Redux level.  That said, I&#39;ve found that it really enables me to think about my data management at a higher level of abstraction.  In addition, its ability to handle relations and simplify the actual logic for immutably updating my data is a real timesaver, and has made a lot of my code simpler in the process.  It&#39;s already served me very well, and I can&#39;t wait to see what other improvements Tommi Kaikkonen might make in the future.&lt;/p&gt;

&lt;p&gt;For links to further information, including documentation and articles, see &lt;strong&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/2016/10/practical-redux-part-1-redux-orm-basics/&#34;&gt;Part 1: Redux-ORM Basics&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Practical Redux, Part 1: Redux-ORM Basics</title>
      <link>https://blog.isquaredsoftware.com/2016/10/practical-redux-part-1-redux-orm-basics/</link>
      <pubDate>Mon, 31 Oct 2016 23:15:00 -0400</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2016/10/practical-redux-part-1-redux-orm-basics/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;h3 id=&#34;intro&#34;&gt;Intro&lt;/h3&gt;

&lt;p&gt;Over the last year, I&#39;ve become a very big fan of a library called &lt;strong&gt;&lt;a href=&#34;https://github.com/tommikaikkonen/redux-orm&#34;&gt;Redux-ORM&lt;/a&gt;&lt;/strong&gt;, by Tommi Kaikkonen.  It helps solve a number of use cases that are common to many Redux applications, particularly related to managing normalized relational data in your store.  I&#39;ve used it heavily in my own application, and have come up with some useful techniques and approaches for using it.  Hopefully you&#39;ll find them useful in your own application as well.&lt;/p&gt;

&lt;p&gt;This first post will cover &lt;strong&gt;reasons why you might want to use Redux-ORM, and the basics of using it&lt;/strong&gt;.  In Part 2, we&#39;ll look at &lt;strong&gt;specific concepts you should know when using Redux-ORM, and some of the ways I use it in my own application&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The code examples in this post are intended to demonstrate the general concepts and workflow, and probably won&#39;t entirely run as-is. &lt;strong&gt;See the &lt;a href=&#34;https://blog.isquaredsoftware.com/2016/10/practical-redux-part-0-introduction/&#34;&gt;series introduction&lt;/a&gt;&lt;/strong&gt; for info on the example scenarios and plans for demonstrating these ideas in a working example application later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: These two posts cover use of Redux-ORM 0.8, but version 0.9 has since been released with several breaking API changes.  The basic usage is still the same, but some aspects of behavior are different.  See &lt;strong&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/2017/07/practical-redux-part-9-managing-dependencies/&#34;&gt;Practical Redux, Part 9: Upgrading Redux-ORM&lt;/a&gt;&lt;/strong&gt; for details on the differences.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&#34;table-of-contents&#34;&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#why-use-redux-orm&#34;&gt;Why Use Redux-ORM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#basic-usage&#34;&gt;Basic Usage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#redux-orm-and-idiomatic-redux&#34;&gt;Redux-ORM and Idiomatic Redux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#final-thoughts&#34;&gt;Final Thoughts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#further-information&#34;&gt;Further Information&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;why-use-redux-orm&#34;&gt;Why Use Redux-ORM?&lt;/h2&gt;

&lt;p&gt;Client-side applications frequently need to deal with data that is nested or relational in nature.  The standard advice for a Redux application is to &lt;a href=&#34;http://redux.js.org/docs/faq/OrganizingState.html#organizing-state-nested-data&#34;&gt;store this data in a &amp;quot;normalized&amp;quot; form&lt;/a&gt;.  For a Redux app, that means organizing part of your store to look like a set of database tables.  Each type of item that you want to store  gets an object that is used as a lookup table by mapping item IDs to item entries.  Since objects don&#39;t have a real sense of order, arrays of item IDs are stored to indicate ordering.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: For further information on normalization in Redux, see the &lt;a href=&#34;http://redux.js.org/docs/recipes/StructuringReducers.html&#34;&gt;Structuring Reducers&lt;/a&gt; section of the Redux docs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because data is often received from the server in nested form, it needs to be transformed into a normalized form to be properly added to the store.  The typical approach is to use the &lt;a href=&#34;https://github.com/paularmstrong/normalizr&#34;&gt;Normalizr&lt;/a&gt; library for this.  You can define schema objects and how they relate, pass the root schema and  some nested data to Normalizr, and it gives you back a normalized version of the data suitable for merging into your state.&lt;/p&gt;

&lt;p&gt;However, Normalizr is really only intended for one-time processing of incoming data.  It doesn&#39;t provide tools for dealing with normalized data once it&#39;s in your store.  For example, it doesn&#39;t include a way to denormalize data and look up related items based on IDs, nor does it help with applying updates to that data.  There are a couple of other libraries that can help, such as &lt;a href=&#34;https://github.com/gpbl/denormalizr&#34;&gt;Denormalizr&lt;/a&gt;, but there&#39;s a definite need for something that can make these steps easier to deal with.&lt;/p&gt;

&lt;p&gt;Fortunately, such a tool exists: &lt;strong&gt;Redux-ORM&lt;/strong&gt;.  Let&#39;s look at how it&#39;s used, and how it can make it easier to manage normalized data within the store.&lt;/p&gt;

&lt;h2 id=&#34;basic-usage&#34;&gt;Basic Usage&lt;/h2&gt;

&lt;p&gt;Redux-ORM comes with excellent documentation. The main &lt;a href=&#34;https://github.com/tommikaikkonen/redux-orm&#34;&gt;Redux-ORM README&lt;/a&gt;, &lt;a href=&#34;https://github.com/tommikaikkonen/redux-orm-primer&#34;&gt;Redux-ORM Primer tutorial&lt;/a&gt;, and the &lt;a href=&#34;http://tommikaikkonen.github.io/redux-orm/index.html&#34;&gt;API documentation&lt;/a&gt; cover the basics very well, but here&#39;s a quick recap.&lt;/p&gt;

&lt;h3 id=&#34;defining-model-classes&#34;&gt;Defining Model Classes&lt;/h3&gt;

&lt;p&gt;First, you need to determine your different data types, and how they relate to each other (specifically in database terms).  Then, declare ES6 classes that extend from Redux-ORM&#39;s &lt;code&gt;Model&lt;/code&gt; class.  Like other file types in a Redux app, there&#39;s no specific requirement for where these declarations should live, but you might want to put them into a &lt;code&gt;models.js&lt;/code&gt; file, or a &lt;code&gt;/models&lt;/code&gt; folder in your project&lt;/p&gt;

&lt;p&gt;As part of those declarations, add a static &lt;code&gt;fields&lt;/code&gt; section to the class itself that uses Redux-ORM&#39;s relational operators to define what relations this class has:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {Model, fk, oneToOne, many} from &amp;quot;redux-orm&amp;quot;;

export class Pilot extends Model{}
Pilot.modelName = &amp;quot;Pilot&amp;quot;;
Pilot.fields = {
  mech : fk(&amp;quot;Battlemech&amp;quot;),
  lance : oneToOne(&amp;quot;Lance&amp;quot;)
};

export class Battlemech extends Model{}
Battlemech.modelName = &amp;quot;Battlemech&amp;quot;;
Battlemech.fields = {
    pilot : fk(&amp;quot;Pilot&amp;quot;),
    lance : oneToOne(&amp;quot;Lance&amp;quot;),
};

export class Lance extends Model{}
Lance.modelName = &amp;quot;Lance&amp;quot;;
Lance.fields = {
    mechs : many(&amp;quot;Battlemech&amp;quot;),
    pilots : many(&amp;quot;Pilot&amp;quot;)
}

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These definitions do not actually need to declare what specific attributes each class has - just the relations to other classes.&lt;/p&gt;

&lt;h3 id=&#34;creating-a-schema-instance&#34;&gt;Creating a Schema Instance&lt;/h3&gt;

&lt;p&gt;Once you&#39;ve defined your models, you need to create an instance of the Redux-ORM Schema class, and pass the model classes to its &lt;code&gt;register&lt;/code&gt; method.  This Schema instance will be a singleton in your application:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import {Schema} from &amp;quot;redux-orm&amp;quot;;
import {Pilot, Battlemech, Lance} from &amp;quot;./models&amp;quot;;

const schema = new Schema();
schema.register(Pilot, Battlemech, Lance);
export default schema;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;setting-up-the-store-and-reducers&#34;&gt;Setting Up the Store and Reducers&lt;/h3&gt;

&lt;p&gt;Next, you need to decide how to integrate Redux-ORM into your reducer structure.  The docs suggest that you should define reducer functions on your model classes, then call &lt;code&gt;schema.reducer()&lt;/code&gt; and attach the returned function into your root reducer using &lt;code&gt;combineReducers&lt;/code&gt; (probably as a key named &lt;code&gt;orm&lt;/code&gt;).  That approach looks roughly like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;// Pilot.js
class Pilot extends Model {
    static reducer(state, action, Pilot, session) {
        case &amp;quot;PILOT_CREATE&amp;quot;: {
            Pilot.create(action.payload.pilotDetails);
            break;
        }
    }
}

// rootReducer.js
import {combineReducers} from &amp;quot;redux&amp;quot;;
import schema from &amp;quot;models/schema&amp;quot;;

const rootReducer = combineReducers({
    orm : schema.reducer()
});
export default rootReducer;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;I personally have taken a somewhat different approach&lt;/strong&gt;.  The majority of my reducer logic is more generic and not class-specific, so I opted instead to write my own slice reducer for this data and just use Redux-ORM as a tool to help with that.  The basic approach looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;// entitiesReducer.js
import schema from &amp;quot;models/schema&amp;quot;;

// This gives us a set of &amp;quot;tables&amp;quot; for our data, with the right structure
const initialState = schema.getDefaultState();

export default function entitiesReducer(state = initialState, action) {
    switch(action.type) {
        case &amp;quot;PILOT_CREATE&amp;quot;: {
            const session = schema.from(state);
            const {Pilot} = session;
            
            // Queue up a &amp;quot;creation&amp;quot; action inside of Redux-ORM
            const pilot = Pilot.create(action.payload.pilotDetails);
            
            // Applies the queued actions and returns an updated
            // &amp;quot;tables&amp;quot; structure, with all updates handled immutably
            return session.reduce();            
        }    
        // Other actual action cases would go here
        default : return state;
    }
}

// rootReducer.js
import {combineReducers} from &amp;quot;redux&amp;quot;;
import entitiesReducer from &amp;quot;./entitiesReducer&amp;quot;;

const rootReducer = combineReducers({
    entities: entitiesReducer
});

export default rootReducer;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;selecting-data&#34;&gt;Selecting Data&lt;/h3&gt;

&lt;p&gt;Finally, the schema can be used to look up data and relationships in selectors and &lt;code&gt;mapState&lt;/code&gt; functions:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;import React, {Component} from &amp;quot;react&amp;quot;;
import schema from &amp;quot;./schema&amp;quot;;
import {selectEntities} from &amp;quot;./selectors&amp;quot;;

export function mapState(state, ownProps) {
    // Create a Redux-ORM Session instance based on the &amp;quot;tables&amp;quot; in our entities slice
    const entities = selectEntities(state);
    const session = schema.from(entities);
    const {Pilot} = session;
    
    const pilotModel = Pilot.withId(ownProps.pilotId);
    
    // Retrieve a reference to the real underlying object in the store
    const pilot = pilotModel.ref;    
    
    // Dereference a relation and get the real object for it as well
    const battlemech = pilotModel.mech.ref;
    
    // Dereference another relation and read a field from that model
    const lanceName = pilotModel.lance.name;

    return {pilot, battlemech, lanceName};
}

export class PilotAndMechDetails extends Component { ....... }

export default connect(mapState)(PilotAndMechDetails);

&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;redux-orm-and-idiomatic-redux&#34;&gt;Redux-ORM and Idiomatic Redux&lt;/h2&gt;

&lt;p&gt;There&#39;s been numerous addon libraries people have built that try to put some kind of OOP layer on top of Redux, as demonstrated by the &lt;a href=&#34;https://github.com/markerikson/redux-ecosystem-links/blob/master/variations.md&#34;&gt;&amp;quot;Variations&amp;quot; page&lt;/a&gt; in my &lt;a href=&#34;https://github.com/markerikson/redux-ecosystem-links&#34;&gt;Redux addons catalog&lt;/a&gt;.  I&#39;ve frequently pointed out that &lt;a href=&#34;https://www.reddit.com/r/reactjs/comments/518qdr/anyone_have_experience_with_jumpsuit/d7arb9g/?context=3&#34;&gt;Redux is primarily focused on Functional Programming principles&lt;/a&gt;, and that &lt;a href=&#34;https://news.ycombinator.com/item?id=11833301&#34;&gt;OOP wrappers over Redux aren&#39;t idiomatic&lt;/a&gt;.  So, given that I usually advise against using those sorts of libraries, you might ask why I encourage the use of Redux-ORM.  What makes it different from other libraries like Jumpsuit or Radical?&lt;/p&gt;

&lt;p&gt;Most of the OOP wrappers I&#39;ve seen try to abstract things away by defining action creators as class methods, and often wind up ignoring the idea of multiple reducers being able to respond to a given action (or even making it impossible).  &lt;strong&gt;They treat Redux as something that needs to be hidden&lt;/strong&gt;, and end up throwing away many of the concepts that make Redux attractive.&lt;/p&gt;

&lt;p&gt;On the other hand, &lt;strong&gt;Redux-ORM doesn&#39;t try to hide Redux&lt;/strong&gt;.    It doesn&#39;t pretend that action constants don&#39;t exist, or that actions and reducers are always a 1:1 correspondence.  It ultimately just provides an abstraction layer over something you would otherwise would have written yourself: CRUD operations for normalized data.  It enables me to think a little less about &amp;quot;What specific steps do I need to follow to update or retrieve this data properly?&amp;quot;, and a little more about handling my data at a conceptual level.&lt;/p&gt;

&lt;h2 id=&#34;final-thoughts&#34;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;Redux-ORM has become a vital part of my toolkit for writing Redux apps.  The data I&#39;m working with is very nested and relational, and Redux-ORM is a perfect fit for my use cases.  Although it&#39;s not yet marked as version 1.0, the API has remained consistent and stable since its inception, and Tommi Kaikkonen has been extremely responsive to issues I&#39;ve filed.  The fact that the library actually comes with real meaningful documentation (both tutorials and API docs) is a huge plus as well.&lt;/p&gt;

&lt;p&gt;Overall, &lt;strong&gt;I highly recommend the use of Redux-ORM in any Redux app that needs to handle normalized nested/relational data&lt;/strong&gt;.  It won&#39;t magically keep you from having to think about managing that data, but it &lt;em&gt;will&lt;/em&gt; make it easier for you to deal with.&lt;/p&gt;

&lt;h2 id=&#34;further-information&#34;&gt;Further Information&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Redux-ORM docs:

&lt;ul&gt;
&lt;li&gt;Project page: &lt;a href=&#34;https://github.com/tommikaikkonen/redux-orm&#34;&gt;https://github.com/tommikaikkonen/redux-orm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Tutorial: &lt;a href=&#34;https://github.com/tommikaikkonen/redux-orm-primer&#34;&gt;https://github.com/tommikaikkonen/redux-orm-primer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;API docs: &lt;a href=&#34;http://tommikaikkonen.github.io/redux-orm/index.html&#34;&gt;http://tommikaikkonen.github.io/redux-orm/index.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Redux docs:

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/faq/OrganizingState.html#organizing-state-nested-data&#34;&gt;FAQ: Handling nested or relational data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/recipes/StructuringReducers.html&#34;&gt;Structuring Reducers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/recipes/reducers/PrerequisiteConcepts.html&#34;&gt;Prerequisite Concepts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/recipes/reducers/NormalizingStateShape.html&#34;&gt;Normalizing State Shape&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/recipes/reducers/UpdatingNormalizedData.html&#34;&gt;Updating Normalized Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://redux.js.org/docs/recipes/reducers/ImmutableUpdatePatterns.html&#34;&gt;Immutable Update Patterns&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Normalizr usage:

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/paularmstrong/normalizr&#34;&gt;https://github.com/paularmstrong/normalizr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/gpbl/denormalizr&#34;&gt;https://github.com/gpbl/denormalizr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://tonyhb.gitbooks.io/redux-without-profanity/content/normalizer.html&#34;&gt;Redux without Profanity: Normalizr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://medium.com/@mcowpercoles/using-normalizr-js-in-a-redux-store-96ab33991369&#34;&gt;Using Normalizr in a Redux Store&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://medium.com/@adamrackis/querying-a-redux-store-37db8c7f3b0f&#34;&gt;Querying a Redux Store&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Discussion:

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.reddit.com/r/reactjs/comments/4hfvwp/complex_hierarchic_state_with_redux/&#34;&gt;Reddit: Complex hierarchic state with Redux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.reddit.com/r/reactjs/comments/3xi2l5/redux_and_relational_data/&#34;&gt;Reddit: Redux and Relational Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.reddit.com/r/reactjs/comments/42070m/reduxorm_a_small_simple_and_immutable_orm_to/&#34;&gt;Reddit: Redux-ORM - A small immutable ORM to manage your Redux store&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.reddit.com/r/reactjs/comments/518qdr/anyone_have_experience_with_jumpsuit/d7arb9g/?context=3&#34;&gt;Reddit: Redux and FP principles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://news.ycombinator.com/item?id=11833301&#34;&gt;Hacker News: Idiomatic Redux and addon usage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    
    <item>
      <title>Practical Redux, Part 0: Introduction</title>
      <link>https://blog.isquaredsoftware.com/2016/10/practical-redux-part-0-introduction/</link>
      <pubDate>Mon, 31 Oct 2016 23:00:00 -0400</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2016/10/practical-redux-part-0-introduction/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;h3 id=&#34;intro&#34;&gt;Intro&lt;/h3&gt;

&lt;p&gt;I&#39;ve spent a lot of time learning about Redux, from many different sources.  Much of my early learning came from reading the docs, searching for tutorials online, and lurking in the Reactiflux chat channels.  As I grew more comfortable, I gained experience answering questions and doing research to help others in Reactiflux, Stack Overflow, and Reddit.  In the course of maintaining my &lt;a href=&#34;https://github.com/markerikson/react-redux-links&#34;&gt;React/Redux links list&lt;/a&gt; and &lt;a href=&#34;https://github.com/markerikson/redux-ecosystem-links&#34;&gt;Redux addons catalog&lt;/a&gt;, I&#39;ve tried to find in-depth articles that dive into some of the complexities and issues involved in building real-world applications, and libraries that help make writing Redux apps better.  Finally, I&#39;ve also pored through numerous issues and discussions in the Redux repo (and even more so now that I&#39;m officially a Redux maintainer).&lt;/p&gt;

&lt;p&gt;In addition to all that research, I&#39;ve also spent much of the last year using Redux in my own application at work.  As I&#39;ve worked on that app, I&#39;ve run into a variety of challenges, and I&#39;ve developed a number of interesting tools and techniques in the process.  Since I&#39;ve learned so much from what others have written, I&#39;d like to start giving back, and sharing what I&#39;ve learned from my own experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This series of posts on &amp;quot;Practical Redux&amp;quot; will cover some of the tips, techniques, and concepts I&#39;ve come up with while building my own application&lt;/strong&gt;.  Since I can&#39;t actually share the specific details of what I&#39;ve built at work, I&#39;ll be making up example scenarios to help demonstrate the ideas.  I&#39;ll be basing the examples on concepts from the &lt;a href=&#34;http://bg.battletech.com/&#34;&gt;Battletech game universe&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;a href=&#34;http://www.sarna.net/wiki/BattleMech&#34;&gt;Battlemech&lt;/a&gt; is a piloted walking robot, armed with various weapons like missiles, lasers, and autocannons.  A Battlemech has one pilot.&lt;/li&gt;
&lt;li&gt;There are different types of Battlemechs.  Each type can have a different size and set of statistics, including what weapons and other equipment it carries.&lt;/li&gt;
&lt;li&gt;Battlemechs are organized into groups of four mechs, called a &lt;a href=&#34;http://www.sarna.net/wiki/Inner_Sphere_Military_Structure#Lance&#34;&gt;&amp;quot;Lance&amp;quot;&lt;/a&gt;.  Three lances make up a &amp;quot;Company&amp;quot;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As the series progresses, I&#39;m hoping to actually start building a small app to show off some of the examples in an actual working environment.  The tentative plan is to build an application that tracks the pilots and mechs in a fictional combat force, like a miniature version of the existing &lt;a href=&#34;http://megamek.info/mekhq&#34;&gt;MekHQ game campaign tracker application&lt;/a&gt;.  These screenshots from MekHQ illustrate some of the concepts and UI that I&#39;m aiming to imitate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://sourceforge.net/p/mekhq/screenshot/Screen%20Shot%202012-09-25%20at%2012.19.38%20PM.png&#34;&gt;MekHQ: List of available pilots and details on selected pilot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://sourceforge.net/p/mekhq/screenshot/Screen%20Shot%202012-09-25%20at%2012.16.47%20PM.png&#34;&gt;MekHQ: Organization tree of mechs and pilots in the force&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://sourceforge.net/p/mekhq/screenshot/Screen%20Shot%202012-09-25%20at%2012.23.30%20PM.png&#34;&gt;MekHQ: Details and statistics for a Battlemech&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I definitely do &lt;em&gt;not&lt;/em&gt; intend to seriously rebuild all of MekHQ&#39;s functionality, but it should serve as a useful inspiration and source of ideas to base my examples on.&lt;/p&gt;

&lt;p&gt;The first couple posts will discuss ways to use the Redux-ORM library to help manage normalized state.  From there, I hope to cover topics such as ways to manage &amp;quot;draft&amp;quot; data while editing items, building a treeview, form input handling, and more.  I also plan to cover some non-Redux-specific topics as well.&lt;/p&gt;

&lt;p&gt;Feedback is always appreciated, whether it be in the comments, on Twitter, in Reactiflux, or elsewhere!&lt;/p&gt;</description>
    </item>
    
  </channel>
</rss>