Retrieving the last post title from Beamer

Upon integrating the Beamer widget in your application, you might have noticed a tooltip appearing over the HTML element you bound to it whenever a new post is published. This feature isn't mentioned in the documentation as far as I can tell, which also implies it cannot be disabled. However, there is a way to do so in JavaScript, and even use the last post title any other way you see fit, even though this information isn't provided to you initially!

The window.Beamer object exposes the ajax method, used by Beamer to request data from its backend: this method is used, among other things, to retrieve the last post title and display it in the aforementioned tooltip. One can use that to their own advantage, and override the method as follows:

let lastPostTitle;
const ajax = window.Beamer.ajax; // keep a reference to the original method...

window.Beamer.ajax = (url, callback) => {
ajax(url, response => { // ...and call it ourselves
try {
// Grab the info for later use if it is available
lastPostTitle = JSON.parse(response).lastPostTitle || "";
} catch (e) {} // fail silently otherwise

callback(response);
});
};

Finally, we can make sure the tooltip is never shown by replacing the method displaying it with a no-op function:

window.Beamer.showLastPostTitle = () => {};

Using expressions as effect dependencies in React functional components

The latest major version of React introduced what has become one of its major features, namely hooks, which enable one to benefit, among other things, from state and lifecycle mechanisms inside a functional component, that is to say one defined as a function rather than a class. The component's lifecycle is thus handled by the useEffect hook, which binds together the behaviours of componentDidMount, componentDidUpdate, and componentWillUnmount. It is used as such:

useEffect(() => {
// This will run upon mounting or unmounting the component,
// as well as everytime it rerenders
});

Of course, this is very rarely what you want: most of the time, you want the effect to run when given props or state values change, which is done as follows:

const [bar, setBar] = useState("");

useEffect(() => {
// This will run when the component rerenders
// because one of the values listed below changed
}, [props.foo, bar]);

You can also pass [] as the second argument to limit the effect's scope to mounting and unmounting of the component.

But you might also want to be nitpicking even more than that: in some situations, it could be ideal to have the effect run based on a computed value. Imagine a component A reading a value from a remote API, and supplying it to its child component B through props; B can then trigger a behaviour in A that would cause that value to change. It is a perfectly valid use case to want to process the first "change" (actually receiving the initial value with a delay) differently than the subsequent ones. Well, the following works just fine:

useEffect(() => {
// This will only run the first time props.foo receives a defined value
}, [props.foo !== undefined]);

This is a pretty helpful workaround to the fact we have no access to effect dependencies' previous values.

In my experience, if you find yourself writing a "complex" effect dependency such as this, half the time there is a simpler solution to your problem; but the other half, knowing this kind of thing is possible can come in handy (and it just makes sense: under the hood, React just matches the values against the previous ones to know whether it should run the effect again or not).

Last but not least, toying around with that dependency list is also useful if a value you depend on is an Object or an Array, since there is a fair chance those are not mutated when their values change, and these therefore cannot be matched against the previous ones:

useEffect(() => {
// This will only run if someArray's contents are actually different,
// even if the parent component overwrote it [thisWay, ...orSomething]
}, [JSON.stringify(someArray)]);

I would be interested to know if other people are using expressions in their effects' dependency lists, so you know what to do!

Handle circular NPM package dependencies with Webpack

If you maintain your own set of JavaScript libraries and publish them on NPM, you might find yourself in a situation where a package A depends on a package B, which in turn depends on A itself. Although you should generally strive to avoid such an ordeal, one can always imagine some edge case where this is a valid way of implementing things. The main problem is that it means each package will require a version of itself installed in node_modules which, on top of being semantically ugly, can make for really painful upgrades, as bumping the version of B in A and then releasing A should be followed by updating to this new version in B, and so forth... so what can we do to avoid this?

The quickest way to break the cycle is to remove A from B's dependencies (or the other way around, depending on what makes the most sense) and add it to its peerDependencies instead. It basically tells your package consumers that the latest compatible version of A should be installed alongside B for everything to work properly, without installing it directly: this transfers responsibility of maintaining the installed version of A onto them. You might also want to add A to B's devDependencies if its presence is necessary for tests to run properly, or anything else related to its maintenance. This should ease the pain within your dependency tree!

Finally, when developing A (which still explicitly depends on B), you might need to set things up so import calls targetting A resolve to your local code, the twin dependency not being around anymore. Doing so depends on your specific build setup, but it is pretty easy to do with Webpack thanks to the resolve part of its configuration:

{
resolve: {
// tell Webpack to look for third-party code in A's root directory before node_modules
modules: [__dirname, "node_modules"],

alias: {
"A": __dirname // tell it to resolve A to this same directory
}
},

// ...
}

This example assumes your entry point (typically index.js) lives in A's root directory; if it rather is is src/, for example, you will want to use path.resolve(__dirname, "src") instead.

Feel free to let me know of a better way to overcome such pitfalls when they cannot be avoided, if you know any!

Overcoming race conditions when using a global event bus in Vue.js

To ease communication between components which are not directly related, and when using a state manager such as Vuex seems overkill, Vue.js developers' go-to pattern is the global event bus: while it feels kind of hacky, it most certainly is easy to both use and reason about.

Or is it though? Depending on your specific use case, there is virtually no guarantee the event listeners will be bound before the events are emitted. Wouldn't it be nice if we had some sort of mechanism that could keep the early-emitted values in memory and apply them upon binding the listeners? Why do I keep asking questions when you know damn well the answer lies right below?

import Vue from "vue";

const bus = new Vue();
const lastValues = {};
const originalEmit = bus.$emit.bind(bus);
const originalOn = bus.$on.bind(bus);

bus.$emit = function(name, value) {
lastValues[name] = value;
originalEmit(name, value);
};

bus.$on = function(name, callback) {
if (lastValues[name] !== undefined) {
callback(lastValues[name]);
}

originalOn(name, callback);
};

export default bus;

This is, too, sort of hacky, but it most certainly does the trick, remains lighter than Vuex, and is conceptually not too far away from immediately-applied watchers one can define in their components. Let me know your thoughts!

Generically overriding component render functions in Vue.js

Besides from using templates, Vue.js components can be set up with a render function, allowing one to programmatically determine their output in a more advanced way. Combining this feature with the HOC pattern, it is thus possible to easily create "augmented" versions of any component in an app, which can come in handy in some situations.

For the sake of example, let's picture a scenario where we have a form, and want to display each of its fields twice: the regular version, and a disabled version, displaying a recommended value based on business rules.

The resulting HOC might look something like this:

import clone from "clone";
import getDisabledVersion from "./getDisabledVersion";

export default function withRecommendedValue(originalComponent) {
const component = clone(originalComponent); // deep-clone component to avoid reference errors
const originalRender = component.render;
const recommendedValue = /* fetch it from wherever */;

component.render = function(h) {
return h("div", {}, [
getDisabledVersion(originalRender.call(this, h), recommendedValue), // disabled doppelganger
originalRender.call(this, h) // original component
]);
};

return component;
}

originalRender.call(this, h) will give us the component's rendered virtual DOM tree as a JSON object, which can then be amended by our getDisabledVersion function, overriding its value and disabled state. The recursive nature of this function implies that it will possibly deal with multiple cases:

  • if our component only contains plain DOM nodes, we will be looking for form controls (i.e. input, select, or textarea) and update their attributes directly; other DOM nodes will be checked for children to call the function upon
  • on the other hand, if our component contains other components, we will rather be interested in their props; specific value handling/transformation that was handled by our own component, if any, will also have to be done here

And this is where the magic happens:

export default function getDisabledVersion(el, value) {
if (["input", "select", "textarea"].includes(el.tag)) {
// Form control node
el.data.domProps.value = value;
el.data.attrs.disabled = true;
} else if (el.componentOptions) {
// Component
// Do dirty things to value if relevant
el.componentOptions.propsData.value = value;
el.componentOptions.propsData.disabled = true;
} else if (Array.isArray(el.children)) {
// Something else, we need to go deeper
el.children = el.children.map(child => getDisabledVersion(child, value));
}

return el;
}

Finally, to use the HOC:

Vue.component("MyComponentWithRecommendedValue", withRecommendedValue(MyComponent));

Of course, with the upcoming uprising of version 3.0 and its composition API, this pattern might soon be a thing of the past; I'm eager to see how it will make this kind of voodoo trick easier (or not). Feel free to drop knowledge about it in the comments if you have some!