Today I Learned

A Hashrocket project

134 posts about #javascript

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.

Get The Location And Size Of An Element

All modern browsers ship with the getBoundingClientRrect() function. It can be invoked for any DOM element. It returns the x and y coordinates of the element within the browser viewport as well as the height and width values and the top and bottom values along the y-axis and left and right values along the x-axis.

> $0.getBoundingClientRect()
{
  "x": 381.421875,
  "y": 70,
  "width": 1030.578125,
  "height": 48,
  "top": 70,
  "right": 1412,
  "bottom": 118,
  "left": 381.421875
}

For instance, this is the result of invoking it against a header element on the MDN page linked above.

Download/Upload Redux Store In Chrome DevTools

People explaining the value of Redux as a JS state solution often point out that it’s designed to support great developer tools. Today I got a better understanding of what that means.

Chrome DevTools currently includes the toolbar shown below. The upload and download buttons, fourth and third from right, allow you to download, inspect (and edit), and upload the Redux store as a JSON file.

This is seems like a fantastic way to debug situations that might be difficult to reproduce through user interactions.

Spread The Rest With ES6

The spread operator provided by ES6 is a powerful syntactic feature. One way it can be used is to capture the rest of an object or array in a variable.

const pokemon = ["Charmander", "Squirtle", "Bulbasaur"];
const [first, ...rest] = pokemon;

console.log("Remaining: ", rest); // Remaining: ["Squirtle", "Bulbasaur"]

const gymLeaders = {
  brock: "rock",
  misty: "water",
  surge: "electric",
  erika: "rainbow"
};
let { brock, erika, ...otherLeaders } = gymLeaders;

console.log(otherLeaders); // Object {misty: "water", surge: "electric"}

Using this spread destructuring we can capture the remaining parts of an array or object in a variable. We can also use this syntax in a function signature to grab specific items from an incoming object argument without losing track of the rest — this is especially useful in React.js development when dealing with incoming props.

This is a stage 3 feature and may not be available in your particular environment.

See a live example here.

Custom Type Checking Error Messages With Yup

In Yup Schemas Are Validated Asynchronously, I showed how to create a simple schema that allows you to enforce that a value is a number.

const numSchema = yup.number();

If we use this schema to validate something that isn’t a number, Yup will provide a lengthy default message. Here is what we get if we validate against 'hey':

this must be a number type, but the final value was: NaN (cast from the value "hey").

This value isn’t necessarily suitable for displaying to a user. We can customize the type checking error message by redefining our schema with the typeError() function:

const numSchema = yup.number().typeError("Invalid number");

Yup Schemas Are Validated Asynchronously

Yup provides a flexible object schema validation DSL. For instance, if you want to enforce that a certain value is a number, you can define something like this:

const numSchema = yup.number();

You can then validate anything against that schema.

const validator = (val) => {
  numSchema.validate(val)
    .then(result => {
      console.log(result); // it is the value of `val`
      return true;
    })
    .catch(error => {
      console.log(error.errors); // array of validation error messages
      return false;
    });
};

The validation is async, so if it succeeds the then block is hit. If the validation fails, it will fall through to the catch.

validator(5) // => true
validator('what') // => false

Promises and then function return values

The return type of Promise function will dictate how future chained then functions behave. If you return a Promise then the next chained then function will execute when the Promise that you returned is resolved.

Promise.resolve('foo').
  then(() => {return Promise.resolve('bar')}).
  then((v) => console.log(v))

// prints bar

If you return something different from the then function, then the argument of the next chained then function will be the previous returned value.

Promise.resolve('foo').
  then(() => {return 'baz'}).
  then((v) => console.log(v))

// prints baz

Check out the MDN docs for Promise.prototype.then

H/T Brian Dunn

H/T Josh Branchaud

Link A JavaScript Package Locally

If you are putting together a JavaScript package and you’d like to test it out locally before putting it on NPM, use npm link.

First, from the directory of the package you are creating run:

$ npm link

This will symlink the package to the global node modules directory.

Then, from the base project directory that you want to try importing and using the package from, run:

$ npm link name-of-package

This will create an additional symlink from the global node modules directory to the node_modules of this target project.

You’ll now have access to the project, try an import to get what you need and try it out.

See man npm-link for more details.

List Top-Level NPM Dependencies

The npm ls command can be used to list all dependencies for a project. This will, however, produce an exhaustive list of all dependencies including dependencies of dependencies. A list this large probably isn’t going to be of much use.

The --depth flag allows you to restrict the depth of the dependency tree that is generated.

$ npm ls --depth=0

This will produce a list of only the top-level dependencies.

See man npm-ls for more details.

New Dates Can Take Out Of Bounds Values

You can create a new date by feeding it arguments for year, month, and day.

> new Date(2017, 11, 31)
Sun Dec 31 2017 00:00:00 GMT-0600 (CST)

What happens if we push the day value out of bounds?

> new Date(2017, 11, 32)
Mon Jan 01 2018 00:00:00 GMT-0600 (CST)

It rolls over to the next month.

Does the same happen when we push the month value out of bounds?

> new Date(2017, 12, 31)
Wed Jan 31 2018 00:00:00 GMT-0600 (CST)

Yep.

What about negative values?

> new Date(2018, -1, 31)
Sun Dec 31 2017 00:00:00 GMT-0600 (CST)

It rolls the month, and consequently the year, back.

Waiting On Multiple Promises

You may find yourself in a situation where you have to request multiple resources from multiple API endpoints and then combine that data in some way.

One way to achieve this would be with nested promises.

fetch('/blogs').then((response) => {
  let blogs = response.body;

  fetch('/tags').then((response) => {
    let tags = response.body;

    // combine blogs and tags ...
  })
})

This nesting isn’t ideal and it can get hard to read as the full implementation is put into place.

The Promise API provides an alternative.

let blogsPromise = fetch('/blogs')
let tagsPromise = fetch('/tags')

Promise.all([blogsPromise, tagsPromise]).then(([blogsResp, tagsResp]) => {
  // combine blogs and tags ...
})

With Promise.all() we are able to wrap any number of promises and wait for all of them to resolve until we do something with the results. This allows us to create a context in which we have all the data we need without a bunch of nesting.

Import All Exports As Object

Here’s a technique for importing constants from a file:

import * as routes from './routes'

This wraps all the exports from routes.js in the object routes. We can access any of those constants like this:

<Route path={routes.exportedPath} />

I like this technique for this use case, because it keeps our import to one line and adds a meaningful namespace.

Fill An Input With A Ton Of Text

I needed to test out a form validation for an input that should render an error when the length of the context exceeds 10,000 characters. Two small tricks make this easy.

First, you can target any DOM element via the Chrome dev tools by selecting it and then referencing it via the $0 magic variable. More details here.

> $0
<input>...</input>

Second, you can quickly and precisely generate a very long string with the repeat function.

> "a".repeat(10000)
"aaaaaaaaaaaaaaaaaaaaaaa..."

Combine these two tricks in the browser to fill the input with a ton of text:

> $0.value = "a".repeat(10000)

h/t Dillon Hafer

ISO-8601 Formatted Dates Are Interpreted As UTC

Using new Date() or Date.parse() with a string that represents a date is a great way to create a Date object for a specified date. A variety of formats are accepted by these methods.

But, caution!

There are subtle differences in how those dates will be interpreted. Given any old string that reasonably represents a date, the date will be interpreted using the local time zone, in my case CST.

> new Date('2017-12-4')
Mon Dec 04 2017 00:00:00 GMT-0600 (CST)

However, as soon as we use an ISO-8601 compliant date format, ECMAScript 5 specifies that the date ought to be interpreted using the UTC time zone. As you can see, the results are drastic enough to affect what day it comes out to.

> new Date('2017-12-04')
Sun Dec 03 2017 18:00:00 GMT-0600 (CST)

Source

Destructuring The Rest Of An Array

ES6 offers some amount of pattern matching on arrays. This means you can do fun stuff like grabbing a couple values and then destructuring the rest of the array into a variable.

> const kids = ["Mike", "Will", "Dustin", "Lucas", "Eleven", "Max"];
undefined
> const [first, second, ...rest] = kids;
undefined
> first
"Mike"
> second
"Will"
> rest
["Dustin", "Lucas", "Eleven", "Max"]

By using the ... syntax with a variable name in the left-hand side of the assignment, you are able to capture an array of whatever isn’t assigned to preceding variables.

Use Decorators for React Higher Order Components

When working with React libraries that make use of higher order components, you wrap your component in a function:

import { withRouter } from 'react-router-dom';

class MyComponent extends Component {
  ...
}

export default withRouter(MyComponent)

When chaining through multiple HOC’s, this can become unwieldly:

import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';

class MyComponent extends Component {
  ...
}

function mapStateToProps(state) { ... };

export default withRouter(connect(mapStateToProps)(MyComponent));

But there is hope, with the decorator syntax in ES6/Babel you can make this look a bit cleaner:

import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';

function mapStateToProps(state) { ... };

@withRouter
@connect(mapStateToProps)
export default class MyComponent extends Component {
  ...
}

Full documentation here.

Alternate names in destructuring assignment

Want to use destructuring assignment, but don’t like the names of the variables as they exist in the object?

If you have data like this:

const optimus = { name: 'Optimus', type: 'Semi-Truck' };
const bumblebee = { name: 'Bumblebee', type: 'Small Car' };

Instead of creating customized variables like this:

const { name, type } = bumblebee;
const bumblebeeName = name;
const bumblebeeType = type;

You can express this type of destructuring in one line like:

const { name: optimusName, type: optimusType } = optimus;

Freeze An Object, Sorta

You can freeze a JavaScript object using Object.freeze which will help enforce some immutability practices. Don’t be fooled though, you can still modify arrays and objects in the frozen object.

Here is what the docs have to say:

The Object.freeze() method freezes an object: that is, prevents new properties from being added to it; prevents existing properties from being removed; and prevents existing properties, or their enumerability, configurability, or writability, from being changed, it also prevents the prototype from being changed.

And here is Object.freeze in action:

> const things = {one: "two", hello: "world", cats: ["Von Neumann", "Sosa"]}
undefined
> Object.freeze(things)
{one: "two", hello: "world", cats: Array(2)}

> things.one = "three"
"three"
> things.dogs = []
[]
> delete things.hello
false

> things
{one: "two", hello: "world", cats: Array(2)}

> things.cats.push("Sneaky")
3

> things
{one: "two", hello: "world", cats: Array(3)}

See the MDN Docs for more details.

h/t Jake Worth

Iterating over objects in Lodash

Many of the Lodash collection functions iterate over either an object or an array. Somewhat unintuitively for me, when iterating over objects the first argument of the iteratee function is a value and the second argument is the key.

The documentation for Lodash lists the arguments for the iteratee in the description for each function. For collection functions that generally looks like this

The iteratee is invoked with three arguments:(value, index|key, collection).

By searching through the documentation for index|key you can find all the functions for which this is true.

Using a Lodash function that can return iterate over an object looks like this:

const result = _.map({a: 1, b: 2}, function(value, key) {
  return value + key;
});

// result is now ["a1", "b2"]

H/T Ryan Messner

`Object.entries` helps you iterate over objects

You may find yourself with an object with lots of entries that you need to transform into an array of extracted information. For examples sake lets say:

  const things = {
    a: 1,
    b: 2
  }

And we need to turn that into and array [2, 3].

We can use Object.entries to turn the object into an array of key/value tuples.

const arr = Object.entries(things)
// arr === [["a", 1], ["b", 2]]

Then we can iterate over that array with map:

const mappedArr = arr.map((tuple) => {
  const [key, value] = tuple;
  return value + 1;
});
// mappedArr === [2, 3]

Object.entries is an ES7 proposal implemented in Chrome/Firefox/Edge and polyfilled with CoreJS, the polyfill library used by Babel.

Compare Form Values with Yup

We’ve been using yup to validate a JavaScript form, and found ourselves facing a common problem when a user signs up for a service:

How do we ensure a user’s email matches their email confirmation?

yup’s test function helped us find a solution. It’s documented like this:

mixed.test(name: string, message: string, test: function)

test takes a name, a message to show on failure, and a function that returns a boolean. We paired this with the email we get from our parent.

var schema = yup.object().shape({
  email: yup
    .string(),
  emailConfirmation: yup
    .string()
    .test('match', 
      'emails do not match', 
       function(emailConfirmation) { 
         return emailConfirmation === this.parent.email; 
       }),
}),

String Interpolation With Template Literals

ES6 adds support for template literals. Template literals make it much easier to compose strings of content — string interpolation. They allow for single and double quotes without having to fuss with escaping. Embedded expressions are also supported which means you can avoid awkward-to-type string concatenation with the + operator.

Here is an example:

> let movie = 'it'
undefined
> `What's up, I just saw "${movie.toUpperCase()}".`
"What's up, I just saw "IT"."

Make console.log stand out with custom css style

I know your browser console is full of messages because you are debugging something, and that creates a lot of noise. Now you are adding a new console.log, and you need it to stand out above the rest.

Maybe you are like facebook and just want to warn your users from pasting in code in the browser in social engineering attacks.

facebook

To style a console.log message use the %c interpolation and pass it a css style. e.g.

console.log('%c%s', 'color:red;font-size:5em', alert)

In the example above %s means inerpolate the object into the output string.

preview

Compatibility: tested to work on Firefox, Chrome, and Safari.

h/t Dillon Hafer

`requestAnimationFrame` should call itself

This style of animation is useful when you’re making small changes via javascript. When you pass requestAnimationFrame a callback, the callback is called before a browser repaint, or about 60 times a second. To make sure that you’re getting 60 callbacks a second, you must call requestAnimationFrame from within your callback.

function animate() {
  makeSomeSmallChangeToHtmlOrCss();
  requestAnimationFrame(animate);
}

This is a recursive function, so without an exit condition, it will recurse infinitely.

H/T Brian Dunn

Tidy your Reducers with `combineReducers()`

Today I learned by necessity the value of the Redux combineReducers(reducers) function.

combineReducers() supports, in a pretty neat way, the crucial Redux task of delegating to reducing functions their own slice of the state.

The documentation example looks like this:

combineReducers({ todos: myTodosReducer, counter: myCounterReducer });

Which we can improve by naming the reducer functions after the state slices they manage, allowing ES6 shorthand notation:

combineReducers({ counter, todos });

This creates a state object like so:

{
  counter: ...,
  todos: ...,
}