TL;DR

by François Vaux

Five-line TailwindCSS-based styled components

I recently discovered TailwindCSS and I think it's a great tool to be able to quickly build fancy websites without spending too much time fiddling with the CSS.

I came up with a five-line React component that let's you write styled-components-like components using Tailwind class names:

import React from "react"
import clsx from "clsx"

export default (Component, ...tailwindStyles) => ({ className, ...props }) => (
  <Component className={clsx(...tailwindStyles, className)} {...props} />
)

(I know, that's actually 6 lines with the blank one 😏)

Usage is very simple as well:

const Warning = styled("div", [
  "my-4",
  "p-4",
  "bg-orange-100",
  "border",
  "border-orange-300",
  "text-orange-800",
  "text-sm",
  "rounded-lg",
  "flex",
])

Bonus points for the regular syntax instead of the funky (read: ugly) mix of template strings and CSS that you're used to with styled-components.

EDIT a few hours later: I realized I was missing the ability to derive styles from props, so I added it!

import React from "react"
import clsx from "clsx"

function isFunction(object) {
  return Boolean(object && object.constructor && object.call && object.apply)
}

export default (Component, ...tailwindStyles) => ({ className, ...props }) => {
  const resolvedStyles = tailwindStyles.map((style) =>
    isFunction(style) ? style(props) : style,
  )
  return <Component className={clsx(...resolvedStyles, className)} {...props} />
}

// Example usage:
export default styled(
  "button",
  (props) => [
    "rounded",
    "py-3",
    "px-4",
    "font-bold",
    "shadow-md",
    "leading-none",
    "focus:outline-none",
    "focus:shadow-outline",
    props.disabled ? "bg-green-200" : "bg-green-400",
    props.disabled ? "text-green-500" : "text-blue-900",
  ],
  (props) => ({
    "hover:bg-green-300": !props.disabled,
    "hover:text-green-800": !props.disabled,
    "cursor-not-allowed": props.disabled,
  }),
)

Recursively invalidating require cache in Node.js

While working on Fluor.js's website, I found myself needing to reload node modules when in watch mode in order to update components used by the generated pages (I'm using Server Side Rendering with React to build the website).

Here's the snippet I used to recursively invalidate a module's cache entry and all its dependencies:

function removeFromCache(moduleId) {
  const cached = require.cache[moduleId]

  if (!cached) {
    return
  }

  // LIB_ROOT and SITE_ROOT are where my source files reside. I avoid reloading
  // node_modules as it causes some issues with the rendering process
  const ownModule = (mod) =>
    mod.path.startsWith(LIB_ROOT) || mod.path.startsWith(SITE_ROOT)

  cached.children.filter(ownModule).forEach((mod) => removeFromCache(mod.id))
  delete require.cache[moduleId]
}

Thinking in React Hooks

React Hooks are a great way to replace class-based components with functional ones in React. This article from Amelia Wattenberger gives an in depth comparison between both approaches, with a lot of helpful visualizations.

How I ditched Redux

Update March 2020: Use useReducer!

Redux is probably the most used state management library for React. However, even its own creator has trouble using it, probably because it is one massive piece of bloat and boilerplate.

I used to solve that problem using elfi, a dead simple state management library that I wrote a few years ago. Elfi is a 50 LOC lib that does not carry any difficult to grasp concepts like reducers, thunks or whatever, but instead only relies on functions.

But given the recent additions to React, even elfi is useless now. Using React Contexts, I simply implement state management in my top level component and pass the state management functions through the context:

// AppContext.js
export const AppContext = React.createContext()

// App.js
function App() {
  // The global application state. We use an object here but an
  // immutable value is also a pretty solid choice
  const [state, setState] = useState({ counter: 0 })

  // The dispatch function updates our state by applying a given
  // function on the previous state
  const dispatch = (fn, ...args) => setState(fn(state, ...args))

  return (
    <AppContext.Provider value={{ state, dispatch }}>
      <Button />
    </AppContext.Provider>
  )
}

// Button.js
function Button() {
  const { state, dispatch } = useContext(AppContext)

  return <button onClick={() => dispatch(increment)}>{state.counter}</button>
}

function increment(state) {
  return { ...state, counter: state.counter + 1 }
}

Try it out on CodePen

The Ultimate Guide to handling JWTs on frontend clients

A great article about how to properly handle JSON Web Tokens in frontend applications.

About this blog

This blog is my personal development blog/journal/notebook hybrid.

I will use it to post (hopefully) daily tips, links or any other Web-development related resources.

As the name suggest, my goal is to keep the posts short and straightforward.