Animated, nestable collapsibles with React

There’s a ton of libraries out there to animate a collapsible element when you aren’t dealing with React, but how do you do it when React is involved? The DOM changes so frequently with every render that you loose references and it makes it difficult to measure. No problem with React references. In fact, while it might seem harder at first to do an animated collapsible with React, its really not much different than if you didn’t use React. React just provides the handy state object for you to store your open/close state in – the rest is the same. To demonstrate this, I’ve created a simple Codepen:

React Performance Learnings

I recently built a React project that dealt with a large amount of data stored in a Redux store that was consumed by a significant amount of components on the page. I knew this might be a performance concern eventually, but React and Redux seemed to be handling it well enough and this project was not a production UI so I tabled optimization.

However, as the complexity of the project grew and more team members were brought in to begin working on it, its deficiencies began to show. Drag-and-drop UI (courtesy of React Beautiful DND) began to slow down, navigation had noticeable delays, all of this exacerbated on my co-worker’s slightly older machine. So, I began to optimize for performance. Here are some of the key take-aways I found:

Large, single Redux store key

If you’ve got a large Redux stored state key (in my case a ~450 item array of objects with about 20 keys each), it can be incredibly slow when making changes to any part of that stored state for any component using pieces of that data set. Due to the nature of the project, a large store of data like this was necessary, so I had to find some workarounds. To keep modification of this data set as minimal as possible I implemented the following strategies:

  1. Only add to the state key when an action is completed
  2. Queue things to be added to the state key in a different Redux state key
  3. Don’t modify items in the state key until a user action is completed
  4. Take things that were modifying items in this large state key and put them in a different Redux state key with data information that allowed me to relate items in the new state key to items in the large state key for comparison

Everything gets updated, all the time…

If you’ve got a component that uses any piece of the global redux state and that piece of the global redux state is modified in any way by any other component – even if the data you’re passing to the component via mapStateToProps you’re dealing with has not changed – it will trigger an update – even though none of your props changed. This cascades down to all of that component’s child components too, so try not to attach a lot of frequently updated properties to your App component or everything gets updated… a lot…

Component has no update checks

This is sort of a “duh”, but React.Component has no update checks, you have to do this manually. Unless you say otherwise, the render() method will be called with any change, even though it may not actually change anything in the DOM. Even though the DOM may not be modified, the processing that leads up to the DOM reconciliation (and the reconciliation itself) done at scale is a big performance hit.

Use PureComponent and Functional components wherever you can

I didn’t want to have to write shouldComponentUpdate checks on every component, especially since React provides a better convention for handling performance concerns like this. So, I converted everything I could into a PureComponent or a Functional component. Extending PureComponent instead of Component automatically adds a shallow compare of the props and state objects to prevent unnecessary updates. This is great to prevent re-renders. Keep in mind that PureComponent components will not re-render any of its child components if it doesn’t also re-render.

Functional components have other means of circumventing constantly re-rendering and are also a great way to keep updates to a minimum. Good rules of thumb to follow:

  1. If you don’t need state, propType validation, or defaultProp settings, make it a Functional component.
  2. If you don’t have a lot of children components that are heavily dependent on multiple state/prop changes from Redux or their parents, make it a PureComponent

Keep reducers simple

I was making redux reducers WAY too complicated. I optimized a TON of code in all my reducers after realizing the simple truth that, what’s returned from the reducer is what the new value will be. This resulted in a great simplification of code there and removal of a dependency on lodash’s cloneDeep (which, while awesome and convenient for deep cloning, is performance costly). For those things I still needed deep cloning, I was able to hack in a little JSON compatible data deep cloning:

Keep in mind that trick only works on JSON compatible data (primitives like Strings, Numbers, Booleans, Arrays, and Object literals). Also, it makes me feel a little dirty because it really is a hack, but hey its fast and works for my data set.

React DevTools FTW

Another “duh”, but when performance debugging, the React DevTools extension was a huge help. Specifically in this case, the Highlight Updates checkbox was a great way to reveal how inefficient my code was :-/

Chrome Debugging in VSCode

I’ve tried giving VSCode a couple of tries in the past and I never could see it replacing my tried and true IDE of choice – Sublime Text …until possibly now. Sublime Text is an amazingly fast editor (faster than VSCode), but for some of VSCode’s quirks, I’m actually finding it to be a potential replacement now in its current iteration, and Chrome Debugger is the real clincher.

Continue reading “Chrome Debugging in VSCode”

A Step-by-step Guide to Creating a Password Protected S3 bucket

In the spirit of “serverless” web applications and websites, this guide will outline how to setup a pasword protected series of files hosted in an S3 bucket – no EC2 layer in-between. This takes advantage of the latest [email protected] features to intercept HTTP requests to CloudFront, which we will configure in front of your S3 bucket.

Continue reading “A Step-by-step Guide to Creating a Password Protected S3 bucket”

Testing nested attributes with RSpec

So I came across a situation today where I needed to have a particular model accept nested attributes for a related model – much like is demonstrated in the post on integrating advanced forms with Cocoon. Unfortunately, much to my dismay, RSpec doesn’t have any fancy convenience method for testing this. Intarwebz to the rescue!

I found this great little script for doing simple testing for nested attributes, including rejection and acceptance criteria. Just place the code from this gist in a file in your spec/support folder and you’ll magically gain access to a new should matcher – accept_nested_attributes_for.

it { should accept_nested_attributes_for(:association_name) }

Login as User WordPress Plugin

When managing a large WordPress community or when your WordPress setup is a little more than a simple blog, it can be useful to see things from your user’s perspective. I have created a simple Must Use Plugin you can just drop into your WordPress installation that allows a Super Administrator user to login as any user on your website (except for other Super Administrators). This is a highly useful functionality when you need to verify that your interfaces are working not only for your Super Administrator roles, but your other user roles as well.

Check out the plugin on GitHub at: https://github.com/kynatro/loginasuser

Easy communication with Rails VirtualBox server

In a recent post I talked about how to setup a Ruby on Rails environment for Mac OS or Ubuntu by itself and in a VirtualBox. In using my VirtualBox Ubuntu server on my Windows laptop, I’ve been annoyed by the constantly changing IP address when networking is configured to Bridge Adapter, so after a little Google sleuthing I was able to find an easy to implement solution: port forwarding. Continue reading “Easy communication with Rails VirtualBox server”

Building a has_many, through model relationship and form with Cocoon

So, I’m working on a personal project to learn Ruby on Rails and the application structure that I desired required a complicated many-to-many relationship with a join model that itself contained data. This was a pretty complex model structure to setup and has numerous pitfall points that took a weekend of searching the Googles and reading a number of StackOverflow entries, GitHub gem documentation and RailsCasts to finally understand and get working the way I desired. Since all the documentation I found only dealt with small pieces of the whole and it took me all weekend to figure it out, I got to thinking there’s no way I’m the only one out there trying to grok this crap. So, now that I got it working, I’m going to share how the heck to do it so you can learn from my guinea pigging.

Continue reading “Building a has_many, through model relationship and form with Cocoon”

Finally a practical use for WordPress’ secret SHORTINIT constant!

Ever write a plugin that needs to utilize AJAX functionality for a rapid response, such as checking if a user exists in the database on key-up, but going through the usual admin-ajax route is too slow? You can write your own AJAX response addressing a PHP file directly with the secret SHORTINIT constant to safely load the WPDB Class and be able to access the WordPress database Object!
Continue reading “Finally a practical use for WordPress’ secret SHORTINIT constant!”