Today I Learned

A Hashrocket project

164 posts about #javascript

Get the return type of a function in TypeScript

Sometimes you only want to rely on the return type of a function instead of defining a new type for it.

To do that in TypeScript use ReturnType and typeof:

function extractStatusData(buffer: Buffer) {
  return {
    active: buffer[0] !== 1,
    totalErrors: buffer[1]
  }
}

function onStatusChange(callback: (data: ReturnType<typeof extractStatusData>) => void) {
  listenToSomeBinaryStuff(buffer => {
    const statusData = extractStatusData(buffer)
    callback(statusData)
  });
}


onStatusChange(({active, totalErrors}) => {
  if (active) {
    console.log(`Task is still running`)
  } else {
    console.log(`Task is completed with ${totalErrors} errors`)
  }
})

The paste event in browsers

Browsers allow you to capture a paste event in a DOM element [1] [2].

This event fires before any clipboard data is inserted into the document, which makes it ideal for manipulating the data and pasting the manipulated data instead.

In Today I Learned by Hashrocket we recently utilized this feature to enable pasting images straight into the post editor. The image is then uploaded to imgur.com and the resulting URL is pasted as a Markdown Image Tag into the textbox.

image

If you are interested in adding similar functionality to your site check out this PR.

Also consider hosting your own fork of TIL.

Install node modules in subdir without a CD

So yea you don’t need a friend to send you a CD-ROM anymore to install node modules. You can use the World Wide Web! Pretty exciting.

On a more serious note, if your front-end is stored in a sub directory of your project, for example:

❯ tree -d -L 2
.
├── assets
|   ├── package.json
|   └── package-lock.json
└── app

Normally you would cd into assets, run npm i, and cd back out to the project root so you can go back to doing important things:

cd assets
npm i
cd -

Or you can push and pop, cause you’re kinda smart

pushd assets && npm i && popd

Or if you’re a really cool kid you’d use a sub-shell

(cd assets && npm i)

But wait! There’s another option - use the prefix CLI option in NPM!

npm i --prefix assets

It works really well for those long Dockerfile RUN statements.

for...in Iterates Over Object Properties

I don’t reach for for loops very often, so when I needed one recently I thought I’d check out the newer for...in construct. It didn’t behave quite how I was expecting. I thought it would iterate over the values in the target list, instead it seemed to be iterating over the indices.

The MDN docs explain what is going on:

The for...in statement iterates over all non-Symbol, enumerable properties of an object.

An array is an object whose properties are the indices of the values stored in the array.

const fruits = ["apple", "banana", "orange"];
for (let fruit in fruits) {
  console.log(fruit, fruits[fruit]);
}
// => "0" "apple"
// => "1" "banana"
// => "2" "orange"

The iteration value wasn’t what I was looking for, but in this case I can use it to access the value from the list. I’d be better off using a standard for loop though.

Imports in ES5

The ES6 import keyword is so pervasive in how we write JavaScript currently that when when I had to “import” the path package in ES5 I didn’t know how to do it!

It’s really easy though, and if you don’t like magic keywords maybe it’s a little more intuitive too.

const path = require('path');

And if something is the default export in it’s module, then you can use the default property.

const Something = require('something').default;

I ran into this in a file that was outside the build path, gatsby-config.js.

Destructured Access To Nested Value & Parent Value

A destructuring pattern that I often see (especially in React code) is to peel off a nested value in the argument declaration of a function.

const Component = ({ data: { name: displayName }}) => {
  return (
    <div>
      <h1>{displayName}</h1>
      <SubComponent />
    </div>
  );
};

On its own this works quite well, but what happens when you need access to the full set of data as well as the nested name value? I often see this.

const Component = ({ data }) => {
  const { name: displayName } = data;
  return (
    <div>
      <h1>{displayName}</h1>
      <SubComponent data={data} />
    </div>
  );
};

ES6 destructuring is flexible. You can skip the const line and keep everything in the argument declaration.

const Component = ({ data: { name: displayName }, data }) => {
  return (
    <div>
      <h1>{displayName}</h1>
      <SubComponent data={data} />
    </div>
  );
};

You can re-reference the data value after the nested destructuring.

Matching A Computed Property In Function Args

The computed property name feature of ES6 allows you to reference a variable in object assignments and destructurings. This syntax is flexible enough that it can be used in the arguments portion of a function declaration. In fact, it can even be matched against another argument — allowing the creation of some handy, yet terse functions.

const get = (key, { [key]: foundValue }) => foundValue;

Notice that the first argument, key, will match against the computed property name in the second argument. The foundValue will correspond to whatever key maps to in the given object.

This get function can then be used like so.

const stuff = { a: 1, b: 2, c: 3 };

console.log("Get a:", get("a", stuff)); // Get a: 1
console.log("Get d:", get("d", stuff)); // Get d: undefined

h/t @sharifsbeat

Javascript Default Named Parameters

I wanted to create a function with some named parameters as optional values, but I wanted them to have a default value for each option. I could use function({max = 10, min = -10}){} but this only works if you pass a js object as argument. So I added a default object into that and it just works great. Check this out:

avg = function({max = 10, min = -10} = {max: 11, min: -11}) {
  let avg = (max + min) / 2;
  console.log('min', min, 'max', max, 'avg', avg);
  return avg;
}

avg();
// => min -11 max 11 avg 0

avg({});
// => min -10 max 10 avg 0

avg({max: 5});
// => min -10 max 5 avg -2.5

avg({min: 6});
// => min 6 max 10 avg 8

avg({max: 5, min: 6});
// => min 6 max 5 avg 5.5

Default values are different on this example for illustration purposes.

Check The Password Confirmation With Yup

The Yup library makes it easy to validate individual values in a JavaScript object. A common situation when implementing a Sign Up form is asking the user to input their password twice and then the app can make sure they match.

To do this, we need the validation of our passwordConfirmation value to reach outside of itself to make a comparison with the password value. This can be done with Yup’s ref function.

import * as Yup from 'yup';

validationSchema: Yup.object({
  password: Yup.string().required('Password is required'),
  passwordConfirmation: Yup.string()
     .oneOf([Yup.ref('password'), null], 'Passwords must match')
});

We are able to reference the value of password with ref. We use the oneOf function to ensure that passwordConfirmation either matches password or if it is left blank and matches null then it passes the validation for the time being. The second argument to oneOf is a custom validation message when this validation fails.

source

Easy Date Comparison With DayJS

Let’s say my application fetches dates from the server which come back in string form as "YYYY-MM-DD" and I’d like to know if those dates already passed. This can be done easily by wrapping dates in DayJS and using its comparison functions.

import dayjs from 'dayjs';

const today = dayjs(new Date());
const pastDate = dayjs("2018-10-22");
const futureDate = dayjs("2022-01-01");

console.log(pastDate.isBefore(today));
// => true
console.log(futureDate.isBefore(today));
// => false

The dayjs() function can be used to construct DayJS date objects from Date objects and strings. These can then be compared with functions like isBefore() and isAfter().

ES6 Nested Destructuring

I picked this up a while ago on Twitter, use it all the time in my React code, and wanted to document it here. If you’re destructuring a JS object like this:

const { username, zip } = props.user;

A valid (and slightly better, in my opinion) refactor is this:

const { user : { username, zip } } = props;

As you add more destructured variables pulled from props, the object you’re referencing stays the same.

Note that this doesn’t define user— if that’s something you want, you have to destructure it on its own:

const { user, user : { username, zip } } = props;

While a little more verbose, I still think this makes for more maintainable destructuring long-term.

Get The Time Zone Of The Client Computer

The resolvedOptions function on Intl.DateTimeFormat.prototype provides a number of pieces of information about the client computer. It includes information such as the locale and the numbering system. It also has the time zone for that machine.

Try running this line of JavaScript in your own browser.

$ Intl.DateTimeFormat().resolvedOptions().timeZone

When I run it, I get America/Chicago.

You can use this within your client-side code as a way of determining in which time zone your users are.

Ignore just one statement with Prettier

Prettier works great for formatting your javascript. In general, it makes formatting something that you don’t have to think about anymore, but occasionally you’ll run across something that you want to format in your own custom way.

You can include a prettier-ignore comment to achieve this goal.

// prettier-ignore
const minesweeperMap = [
    'B', ' ', ' ',
  ' ', 'B', ' ',
  'B', ' ', ' ',
  ' ', ' ', 'B',
];

const bombs =     4;

When you run prettier on the above code, the declaration of bombs line will be changed to remove unneeded spaces, but the minesweeperMap declaration will be left unchanged.

Notify your application when browser goes offline

At JS Camp this past weekend I saw Josh Beckman give a talk about the appropriate time to trigger a page refresh when the single page application has received some updates.

A key component of that is knowing whether you have an internet connection or not.

Fortunately there is a browser event, offline, that will help you keep track of your offline status.

window.addEventListener('offline', () => console.log('is offline'))

When I turn the wifi off, then is offline is logged to the console.

You can also take advantage of the navigator.onLine (yes a capital L) property to determine whether your application currently has an internet connection.

Rendering Emojis With Unicodes in Javascript

Ordinarily you can render an emoji in Javascript by using its four-character Unicode code point as follows:

(React JS [JSX] Sample)

<span>{'\u263B'}</span> => <span>☻</span>

Sometimes, however, the Unicode code point for an emoji is more than four characters long and the above method for rendering doesn’t work. In ECMA6, the following syntax will work for emojis whose Unicode code point length is more than four (1):

<span>{'\u{1F4A9}'}</span> => <span>💩</span>

Note:

  1. This has only been tested with a five-character Unicode code point.

Speed up webpacker by excluding dev dependencies

In our latest project, we were experiencing some long build times after accreting features for a few monhts.

By default webpacker pulls in all of your node_modules for parsing and optimization by babel, which can be quite unneccessary. In order to exclude your devDependencies from that process, you can add the folling code to your development.js config:

...

var package = require('../../package.json');
var excluded = Object.keys(package.devDependencies).map(function(dep){
  return new RegExp("node_modules/" + dep);
});

module.exports = merge(environment.toWebpackConfig(), customConfig, {
  module: {
    noParse: excluded
  }
});

The noParse option can possibly lead to errors when some packages are excluded from parsing (notably, css-loader), you can tweak which dependencies reside in dependencies vs devDependencies in your package.json in order to avoid these issues.

Pass arguments through to wrapped function

If you want to have a function that wraps another function it’s convenient to not worry about the details of the arguments being passed.

I have this:

sendMessage = (name, num) => () {
  console.log(name, num);
}

And I want to wrap it with this:

wrapper = (func, name, num) => () {
  func(name, num);
}

Not all functions I want to wrap have the arguments name and num. To genericize this I can use ...args in the signature to turn all the remaining args into an array and then use ...args again to spread the array into the argument positions of the function call.

wrapper = (func, ...args) => () {
  func(...args);
}

To have the same operator (...) do opposite things based on the context is a little bit weird to me, but that’s ES6!

Custom Cypress Commands

I’ve been loving my first forays into Cypress integration testing. It feels really well made.

Today I learned how to create a custom Cypress command. Logging into the application is a classic use-case: I need to do it in almost every test, and I’d like a function that accepts arguments and centralizes the DOM manipulation.

Here it is:

// cypress/support/commands.js

Cypress.Commands.add('signIn', ({ email, password }) => {
  cy.visit('/sign-in');
  cy.get('input[name="email"]').type(email);
  cy.get('input[name="password"]').type(password);
  cy.get('form').submit();
});

The command is now available in any test without an explicit import:

cy.signIn({ email: 'dev@hashrocket.com', password: 'password' });

Abstraction!

docs

Assigning, Mutating, and Freezing a JS object

I’ve been using Object.assign to merge two objects in javascript. That typically looks like this:

> let o = Object.assign({a: 1, b: 2}, {a: 3})
{a: 3, b: 2}

The key/values in the second argument override the key/values in the first object to produce a new object with those the combined keys and values.

Does it actually produce a new object? or does it just mutate the first argument:

> foo = {a: 1, b: 2}
> bar = Object.assign(foo, {a: 3})
> foo == bar
true
> foo
{a: 3, b: 2}

Ahh… it mutates. If you prefer something not to mutate you can freeze it:

> foo = {a: 1}
> bar = Object.freeze(foo)
> Object.assign(bar, {a: 2})
TypeError: Cannot assign to read only property 'a' of object '#<Object>'

Ok, so now Object.assign can’t mutate the first argument, because that argument is frozen. But be careful, freeze mutates too.

> Object.assign(foo, {a: 2})
TypeError: Cannot assign to read only property 'a' of object '#<Object>'

`classList.toggle()` 2nd arg doesn't work in IE11

Months and months ago I faced a situation where I had to remove an element’s class outside of the react render tree.

Because toggle was being used to add the class in the code previously I used to toggle to remove it, and to ensure that it was removed and not added I used the second argument which would force it to be removed.

Today I learned that the second argument does not work in IE11.

In general, using toggle is an anti-pattern because it’s non deterministic, it depends on state that is unavailable to you when writing the code.

There are methods add and remove for classList, they have some IE11 edges too, but are more explicit about their intention.

See more info here.

Limiting Regex Alternation

The pipe operator (|, or the ‘alternation’ operator) is the ‘or’ of Regexes. Here’s a JavaScript example:

> 'hello'.match(/^hello|goodbye$/)
[ 'hello', index: 0, input: 'hello' ]
> 'goodbye'.match(/^hello|goodbye$/)
[ 'goodbye', index: 0, input: 'goodbye' ]

You might think this Regex can be true in two situations: the string is 'hello' or 'goodbye', because the Regex includes the start-of-line and end-of-line characters (^ and $). I have bad news:

> 'hello there'.match(/^hello|goodbye$/)
[ 'hello', index: 0, input: 'hello there' ]

What’s going on here? This is truthy because the | has a low precedence. It’s evaluated last, after other characters like () and ?. To put this Regex into words (I think): “does this string match anything before the pipe (including the start of line character), or anything after the pipe (including the end of line character)?”. The expression matches on ^hello and ignores anything after that.

We can contain it by telling the pipe to stop evaluating. Parentheses work because they have a higher order of precedence. Here’s our new Regex:

> 'hello there'.match(/^(hello|goodbye)$/)
null
> 'say goodbye'.match(/^(hello|goodbye)$/)
null

Bottom line: when using the pipe the way I’ve described, use parentheses.

NODE_OPTIONS without node

I was using storybook and found it had grown so large that its node process would run out of memory before it could start. The downside was that the storybook command did not accept node arguments, like --max_old_space_size=4096

Starting with node 8, node will look for options in an environment variable named NODE_OPTIONS to be interpreted as if they had been specified on the command line before the actual command line (so they can be overridden).

Example to give storybook more memory:

NODE_OPTIONS=--max_old_space_size=4096 storybook start

*References:
https://storybook.js.org
https://nodejs.org/dist/latest-v8.x/docs/api/cli.html#cli_node_options_options

Create A Cancelable Promise With PCancelable

If an async task takes a really long time and we find out in the middle of its execution that we no longer want the results of that activity, it would be nice to be able to cancel that promise. There was a proposal for cancelable promises, but it has since been withdrawn. There is an alternative though.

The p-cancelable package provides a promise wrapper that acts as a cancelable promise.

import PCancelable from 'p-cancelable';

const fetchPromise = new PCancelable((resolve, reject, onCancel) => {
  setTimeout(() => {
    resolve({ ok: true, data: [1, 2, 3] });
  }, 10000);

  onCancel(() => {
    console.log('Promise is being canceled');
  });
});

fetchPromise.then(response => {
  console.log('Promise Resolved: ', response.data);
}).catch(err => {
  console.log('Promise Rejected: ', err);
});

fetchPromise.cancel();

We can create a promise in a familiar manner. We get an additional argument — the onCancel function. This is a function that will be executed if cancel is called before the promises has resolved or rejected. In the above example, the fetchPromise.cancel() line will be invoked before the setTimeout resolves. The promise will be canceled, causing a rejection which will push us into the catch handler.

Interval Comparison in JavaScript

Today I learned a bit about interval comparison. It’s something you might recall from grade-school math:

1 < 5 < 10 -- is this true?

Two languages I’ve found that support it are Python and Clojure:

> if (1 < 5 < 10):
...   True
...
True
> (< 1 5 10)
=> true

JavaScript doesn’t support interval comparison, so we have to find another way to check that condition. Here’s one technique:

if (1 < number && number < 10) {
  // do something
}

It’s a wordier that the previous examples, but I think keeping the variable in the middle of the condition stays true to the interval comparison idea.

Create An Object With No Properties

When you call new Object or even just instantiate an object with {}, you are creating an object that uses the Object prototype. This means it inherits from Object.prototype.

You can deliberately create an object with no properties by making sure that it does not inherit Object.prototype.

> const propertylessObject = Object.create(null);
{}

> propertylessObject.__proto__
undefined

Unlike most objects that we encounter as we write JavaScript, this object we created with Object.create(null) has no properties including no __proto__.

See Object.create and Object.prototype for more details.

Turn Off Console Error Messages In A Test

I’m using Jest to test a React component that requires a prop via PropTypes. In one of my tests, I want to test that component when the required prop is excluded. The side effect of doing this is that my test output gets cluttered with the PropType warning.

The thing to do is silence the error message during that test.

it('renders a component without a required prop', () => {
  const originalError = console.error;
  console.error = jest.fn();

  // test code here
  expect(shallow(<My Component />)).toDoSomething;

  console.error = originalError;
});

We can silence console.error by temporarily replacing it with a Jest-mocked function and then putting it back at the end of the test.

Using `yarn global` w/ Node through asdf (mac)

The asdf version manager is an awesome tool for managing many different language runtime versions. I recently started using it for Node and noticed that yarn global no longer plays nice with it.

Turns out that if you install yarn through homebrew - your global directory will not take into account the asdf node version and path.

To correct this, first uninstall yarn from homebrew:

brew uninstall yarn

Then in your .zshrc or equivalent remove the yarn global path (see my previous post about Yarn global)

Now you want to find where asdf is being sourced into your .zshrc and insert a dynamic yarn global path:

~/.zshrc

# asdf global version manager
source "$HOME/.asdf/asdf.sh"
source "$HOME/.asdf/completions/asdf.bash"

# set yarn binaries on path
# must be below the .asdf source commands ^
export PATH="$(yarn global bin):$PATH"

You can now install yarn again from npm which will put it in your asdf versioned node:

npm i -g yarn

When done restart your terminal and test to see that everything worked. I had to delete the ~/.config/yarn/global to make this work.

echo $PATH should contain something that looks like /Users/dkarter/.asdf/installs/nodejs/9.11.1/.npm/bin which should match yarn global bin.

Custom errors in JavaScript ⚠️

Javascript provides the ability to create custom errors by modifying the prototype of a function to the Error protorype. This is how one would create a custom error:

function ValidationError(message) { 
  this.name = 'ValidationError'; 
  this.message = message; 
}
ValidationError.prototype = Error.prototype;

// USAGE
throw new ValidationError('the form is invalid');

To catch it you can check the class of an error using instanceof:

try {
    // do stuff
  throw new ValidationError('the form is invalid');
} catch (ex) {
    if (ex instanceof ValidationError) {
    alert(ex.message); // the form is invalid
  } else {
    // crash and burn
    throw ex;
  }
}

📅 Get begining and end of week with Moment.js

To get the date for benining of week for a date in moment you can use the startOf and endOf functions on moment objects.

const today = moment();
const from_date = today.startOf('week');
const to_date = today.endOf('week');
console.log({
  from_date: from_date.toString(),
  today: moment().toString(),
  to_date: to_date.toString(),
});

// {
//   from_date: "Sun Apr 22 2018 00:00:00 GMT-0500",
//   today: "Thu Apr 26 2018 15:18:43 GMT-0500",
//   to_date: "Sat Apr 28 2018 23:59:59 GMT-0500"
// }

NOTE: Remember that the start of week will depend on the user’s locale settings on their machine. If you want to use start of week based on ISO 8601 you can use moment().startOf('isoWeek');

The same technique can be used for start of month (startOf('month')), start of year (startOf('year')) and even quarter (startOf('quarter');).

Fix Timeouts and Speed Up Jest on CI

If you have a large or complex test suite, running Jest on CI can make your build especially slow or cause timeouts. Luckily, Jest has an option cut out for this.

jest --runInBand

runInBand runs all tests serially inside the current process instead of creating a bunch workers. Using this option, we were able to trim suite time above 20mins down to less than 4 mins. 🏎️😎

Configure Jest To Run A Test Setup File

Jest can be configured to run a setup file before each test. This is useful for configuring your testing framework in a single place, rather than in each test file.

This setup file can be specified in package.json (or jest.config.js).

// package.json
{
  // ...
  "jest": {
    "setupTestFrameworkScriptFile": "<rootDir>src/setupTests.js"
  }
}

The setupTestFrameworkScriptFile points to a test setup file at the specified location rooted at <rootDir> (the root of your project).

This kind of setup is helpful for something like Enzyme that needs to be configured with a specific adapter for use throughout your tests.

Check If Something Is An Array

The Array class has a function on it called isArray() which can be used to check if something is an array.

> Array.isArray('Hello, World!');
// => false

> Array.isArray(['One', 2, [3]]);
// => true

> Array.isArray({ foo: 'bar' });
// => false

> Array.isArray([]);
// => true

The MDN docs provide an example polyfill if it is not natively available.

if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}

Resolve And Pass Multiple Values From A Then

Let’s say you are chaining multiple async function calls together.

fetchTrainer(trainerName)
  .then(response => {
    const trainerData = response.body;

    return fetchPokemonFor({ trainerId: trainerData.id });
  })
  .then(response => {
    // I want trainerData, but it is now out of scope...
  });

But in the last then() you want access to both the trainerData and the pokemonData. So, how do you pass both the trainerData and the resolved response of fetchPokemonFor() through to that last then().

fetchTrainer(trainerName)
  .then(response => {
    const trainerData = response.body;

    return Promise.all([
      trainerData,
      fetchPokemonFor({ trainerId: trainerData.id })
    ]);
  })
  .then(([trainerData, pokemonResponse]) => {
    const pokemonData = pokemonResponse.body;

    // do something with trainerData and pokemonData
  });

Promise.all allows us to resolve and pass multiple promises. If any of the values in the array argument is not a promise, it simply passes it through.

h/t Brian Dunn

Reach Into An Object With Nested Data With Get

Among the many lodash utilities is _.get for getting data from nested objects. You can specify where to reach into the nested data of an object using a path.

Consider the following awkwardly nested object:

const resp = {
  error: {
    errors: [
      { message: "Something went wrong" },
    ],
  },
};

Here is how we might reach into this with vanilla JavaScript:

resp.error.errors[0].message;

Reaching into this for the message value is tricky because as soon as the resp object contains differently nested data, an error is likely to be thrown. We can simultaneously avoid a bunch of exception handling logic and provide a default value with the _.get function:

_.get(resp, 'error.errors[0].message', 'Default error message');

If we decide to not include a default value, then undefined will be used.

Mock A Function With Return Values Using Jest

Jest provides a collection of utilities for working with mocked functions. To create a mock function, do:

jest.fn()

// assign it to a variable
const fakeFunc = jest.fn();

// pass it as a prop
<SpecialInput handleChange={jest.fn()} />

A mocked function can then be attributed with a return value.

const fakeFunc = jest.fn();
fakeFunc.mockReturnValue("hello");
fakeFunc(); // => "hello"

The mockReturnValue() function ensures that the value is returned whenever your function is called.

We can also limit the return value to occurring just once.

const fakeFunc = jest.fn();
fakeFunc.mockReturnValueOnce("hello");
fakeFunc(); // => "hello"
fakeFunc(); // => null

mockReturnValueOnce() ensures the value is returned once and all subsequent calls yield null.

Array concatenation with the spread operator

The spread operator in ES6 javascript is a swiss army knife of wonders. Previously in javascript if you wanted to concatenate two arrays you could use the concat method of an array.

let a = [1, 2, 3]
let b = [4, 5, 6]
a.concat(b) //concat though is not mutative, you have to assign the result
let c = a.concat(b) // we have concatenated

Whether or not Array.prototype.concat is mutative has always been something I get wrong. Some Array methods are mutative some are not! By using the spread operator, I never get this wrong (it’s not mutative).

let c = [...[1, 2, 3], ...[4, 5, 6]]
console.log(c) // [1, 2, 3, 4, 5, 6]

Async/Await UnhandledPromiseRejectionWarning

When an await promise is rejected when using async/await you get an UnhandledPromiseRejectionWarning.

promise13 = () => {
  return new Promise((resolve, reject) => { reject(13)})
}

(async () => {
  let num = await promise13(); // UnhandledPromiseRejectionWarning
  console.log('num', num);
})();

There are two ways to properly handle the promise reject. The first is with a try catch block.

(async () => {
  try {
    let num = await promise13();
    console.log('num', num);
  } catch(e) {
    console.log('Error caught');
  }
})();

The second is by handling the error on the promise itself.

(async () => {
  let num = await promise13().catch((err) => console.log('caught it'));
  console.log('num', num);
})();

Both ways will allow you to avoid the UnhandledPromiseRejectionWarning and also properly handle your rejections. Beware the deprecation message that comes with this warning.

Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Create an NVM Config File

NVM supports a configuration file; the most basic file would declare your Node version of choice. Assuming you’re using that Node version, here’s a foolproof method to create such a file:

$ node -v > .nvmrc

I ran this in a project I’m working on, and it exposed a syntax issue with my .nvmrc; I had initially typed 9.2 instead of v9.2.0, the syntax NVM expects. This command eliminates errors like these.

Test Coverage Stats With Jest

Jest is a delightful tool for JavaScript testing from Facebook. As your project evolves and you add tests (or perhaps choose to not add tests) you may wonder what kind of test coverage you have. What is the overall coverage? Which files are well covered and which are seriously lacking?

Use the --coverage flag to get this information.

$ jest --coverage

After running all of your tests a table will be output to the terminal with a list of files and their respective coverage percentages in terms of statement, branch, function, and line coverage.

---------------------------|----------|----------|----------|----------|----------------|
File                       |  % Stmts | % Branch |  % Funcs |  % Lines |Uncovered Lines |
---------------------------|----------|----------|----------|----------|----------------|

This can help guide you to what parts of your app may need more testing.

Toggle Apps with Redux Stores

Another cool feature of Redux DevTools!

With this tool, we can toggle between any open browser tab with a Redux store, inside the tool:

In this GIF I’m clicking the downward arrow in the upper right. Works the same in Chrome and Firefox.

I’m unsure what problem this solves, but I think it does help promote and educate us about Redux by making other Redux-connected apps easily discoverable via DevTools.

Adding Decorators (And Store) To Storybook

We’ve been using Storybook to build and refine React components.

As we blur the boundary between the tool and our application (for example, importing an application component into a Storybook component) the workflow becomes complicated by dependencies like Redux. Storybook suddenly needs to know about the store.

There are multiple ways to handle this; the first is importing store at the top of you Storybook component hierarchy, then passing it as a prop all the way to the Redux-aware component.

A second is Storybook’s addDecorator function. With it, we can wrap the added component in Provider with store, allowing connect() calls to Redux:

storiesOf(‘My Components’, module)
  .addDecorator(getStory => <Provider store={store}>{getStory()}</Provider>)
  .add(‘Redux Aware Component’, () => <ReduxAwareComponent />);

Now we have a Redux-connected component in Storybook.

Get the response json with `fetch` and `Promises`

The fetch api is intertwined with the Promise api. The fetch function itself returns a Promise. The success function for that promise will have an argument that is a Response object.

fetch('myResource.json').then(function(response) {
  console.log('This is a response object', response);
})

The Response object implements Body which has several properties and several methods that help you to access the contents of the body of the response.

Body.json() is a function that reads the response stream to completion and parses the response as json. This operation may take take time, so instead of just returning the json, it returns another Promise. The success function of this promise will have the resulting json as an argument.

fetch('myResource.json').then(function(response) {
  response.json().then(function(parsedJson) {
    console.log('This is the parsed json', parsedJson);
  })
})

Of course, if you return a promise from a success function, then that promise will be resolved in the next chained then function.

fetch('myResource.json').then(function(response) {
  return response.json();
}).then(function(parsedJson) {
  console.log('This is the parsed json', parsedJson);
})

Share SCSS Variables with Javascript

When working with React and Sass, sometimes you want to be able to share variables defined in the stylesheets with your React javascript code. This is actually pretty simple with Webpack.

First make sure webpack is set up to import scss:

// webpack.config.js
module.exports = {
  ...
  module: {
    rules: [{
      test: /\.scss$/,
      use: [{
        loader: "style-loader" // creates style nodes from JS strings
      }, {
        loader: "css-loader" // translates CSS into CommonJS
      }, {
        loader: "sass-loader" // compiles Sass to CSS
      }]
    }]
  }
};

Then define your variables export file:

// variables.scss
$white-color: #fcf5ed;
$dark-color: #402f2b;
$light-color: #e6d5c3;
$medium-color: #977978;
$alert-color: #cb492a;
$light-black-color: #706e72;
$black-color: #414042;

// the :export directive is the magic sauce for webpack
:export {
  whitecolor: $white-color;
  darkcolor: $dark-color;
  lightcolor: $light-color;
  mediumcolor: $medium-color;
  alertcolor: $alert-color;
  lightblackcolor: $light-black-color;
  blackcolor: $black-color;
}

Now you’re ready to import your variables to use with your React components:

import variables from 'variables.scss';

const CSS = {
  backgroudColor: variables.blackcolor
}

export default ({}) => {
  return <div style={CSS}>Content</div>
}

Scoping Variables With A Block Statement

A solid way to keep code readable and easy to understand is to ditch the terse one-liners in favor of breaking things up across multiple lines and using self-documenting variable names. This isn’t all good though. Each new variable that is defined is a handle on some data that can be misused later in the syntax scope.

JavaScript has a nice way of being clear about the scope of certain variables:

let parsedDate;
{
  let [month, day, year] = input.split('-');
  parsedDate = new Date(year, month, day);
}

// do something with parsedDate

The month, day, and year variables are scoped to the { ... } which is a block statement. This helps communicate and enforce that those variables are only to be used in that very specific context. Other developers and our future selves won’t be able to erroneously use those variables.

Of course, breaking out a function is another way of accomplishing this. Sequestering code in a different part of the file is not always the best answer though. Sometimes you want it locally fenced off. For those times, use a block statement.