TodayILearned, Work Projects

TIL… How to use Map and Reduce

While working on a React app, I needed to translate a bit of Redux shape into one needed by an Api. Due to the normalization we imposed on the Redux state, I had to navigate to the desired information through s couple of lists. These entities each had a list of ids of children, and I needed the grand-children of a given entity.

Instead of manually composing this list, I found map and reduce were far better suited to the task, as you might imagine. In order to get the list of grandchildren, I first mapped the list of children ids to a list of lists of grand-child ids. These lists were accessed through the children. Then I took the list of lists and reduced it , effectively merging it into a single, long list of all grandchildren. Helpful hit, always include an initial value for the list. It helps avoid bugs when inputs are empty. Finally I mapped the list of grand-child ids to the grandchildren themselves.

As an experiment I did try to manually iterate through the lists without Map and reduce, and found that those three lines replaced something like 12-15 lines. Further, the 12-15 line code was… obtuse at best. Got to love it when succinct code is also easier to understand.

Advertisements
Standard
TodayILearned, Work Projects

TIL… Combine Reducers also splits state…

While starting work on a greenfield project, I was of course writing new reducers. This time, we were trying to follow a better paradigm as outlined here. As it happens I was writing the byId reducer for an action when I learned a wonderful, simplifying fact.

As you know Reducers take current state and an action, returning a modified state. But what is the state handed to the function? As it turns out, CombineReducers, also splits out the relevant part of state for the given reducers.

For example, take the following Redux State:

root :
    entities:
        item:
            byId
            allIds
        thing
        box
    uiState

If you compose root from an entities and uiState reducer, then the entities reducer gets only the entities part of state. Going deeper you can similarly compose the entities reducer from item, thing and box. The item reducer will only get the item part of state, and will not see anything related to thing or box.

As a result of this behavior, you can write very simple reducers. And of course it is super easy to write tests for reducers composed in this manner.

Standard
TodayILearned, Work Projects

TIL… How to handle User input with a generic function

While writing a CRUD screen with validation in React, I found I was writing similar, if not the same state-altering functions for each input box. Some functions needed additional validation while others did not. After discussing some team-members, the suggestion was made to use the following:

handleUserInput(e) {
   const name = e.target.name;
   const value = e.target.value;
   this.setState({ [name]: value });
}
Paired with code like this for the inputs:
<TextInput
   id="saleName"
   name="saleName"
   placeholder={''}
   value={this.state.saleName}
   onChange={this.handleUserInput}
/>
Then just set the name property on the tag to the same property name in state.
Standard
TodayILearned, Work Projects

TIL… How to delete a property from a javascript object

While working in a reducer, I found I needed to close/remove an entry from a dictionary. After a brief amount of digging I found that I did not have to write this functionality myself.

The kind folk of Lodash have you covered. Simple _omit_ the property. Like so:

import omit from 'lodash/omit'

default export (object)=>omit(object,removedKey);

Lodash/Omit kindly returns a new object, omitting the given key.

Standard
TodayILearned, Work Projects

TIL… How to reduce NPM package size

One of my colleagues was working on improving the load time for a heavy-lifting component in our React App. The component is packaged as an npm package so that it can be reused in other projects, but it is significant in size.

My colleague showed me a nice visual tool for identifying packages in the dependencies which could be shrunk or removed. He added a plug-in to our webpack build which provided a useful visualization of the package structure and hierarchy.

To do this you need to add the following to the webpack.config:

const { BundleAnalyzerPlugin } = require(‘webpack-bundle-analyzer’);
config.plugins.push(new BundleAnalyzerPlugin());
You’ll also need to install the webpack-bundle-analyzer package.
Using this tool we were able to see that some of the large size was due to duplications of modules. That is the user project, and the project we were working on shared dependencies.
My colleague solved this in two ways, first he removed the Node Modules folder from web-pack, thus removing it from the final bundle. Second, he made sure that the project we were improving, and the user project shared the same version of as many dependencies as possible. By doing so my colleague was able to greatly improving the loading time for this npm package.
Standard
TodayILearned, Work Projects

TIL… How to add Raygun to a React App

We were preparing to roll-out our brand spanking-new React App. Naturally once our app is out in the wild we wanted to have telemetry on it. The client’s go-to telemetry provider was Raygun.I was blessed and impressed with how excellent Raygun’s documentation was!

It was so accurate and easy to follow, I can’t put it in better words myself. However I did run into one sticky issue while integrating. Specifically, integrating the React-Router pages and Raygun’s page-view logging. To be sure, Raygun provides a good method for doing this, one simply adds a listener to the props.history object provided by React-Router.

Prior to using Raygun the app relied on BrowserRouter, which creates a history object under the hoop. But the Router object allows the developer to provide a history object. So the easiest way to attach the Raygun listener is to call createBrowserHistory, and then attach to the history object before giving it to the Router. Also if you are using a baseUrlName in you app, be sure to pass that to the createBrowserHistory call!

Standard
TodayILearned, Work Projects

TIL… How to manually redirect within React-Router

While working on a SPA react application, I noticed that every time I returned from one screen to the first, I was resetting the Redux state. Given we were using React-Router to handle ‘pseudo’ links, I was very confused.

As it turns out, the way I was redirecting was the culprit. The SPA was supported by an MVC controller, and route. Since we were using React-Router, we had a catch-all route so that the controller would still render the same action despite route changes.

Normally, routes are changed within the SPA using RouterLink or similar constructs. Since my redirect was happening as part of an action I was changing the window.history. That was what caused the problem.

I found later that I was causing the browser to fix a new request to the server, rather than relying on the React-Router to determine the course. Thankfully, components rendered by a Router receive a prop called history. This props.history is managed by the React-Router, and pushing to it will cause the Router to handle the redirect, thus preserving the Redux state.

Standard