DEV Community

loading...
Cover image for Currying with React

Currying with React

jo3w3bd3v profile image Joseph Evans ・3 min read

Currying may or may not be an alien concept to many of you & if you know myself at all, you'll know that I enjoy currying. No I won't make a reference to delicious dish that is curry, whilst I'm a foodie, that's totally off topic. If you'd like to generally get a better idea of what currying is, then read this pretty awesome post!

When using React, in my opinion it makes sense to utilise currying, whether that's a means of passing hooks to child components via props. But I find it effective when trying to encapsulate business logic away from the component itself, in the event where you want to trigger something on a given event, let's say click, how would you do this? How would you pass in arguments without just creating a call back wrapper of some sort?

An example of where this wouldn't work:

import React, { useState } from 'react';

const clickHandler = (state, e) => console.log(e.target);

export default (props) => (
  const [state, setState] = useState({});

  <button onClick = {clickHandler(state)}>{props.text}</button>
);
Enter fullscreen mode Exit fullscreen mode

If you tried to do this then it wouldn't behave quite like you'd hope, assuming that you'd want to pass the value of state into the click handler function & the event object. That's fine though, all you'd have to do in order for this to work as you'd expect is this:

import React, { useState } from 'react';

const clickHandler = (state) => (e) => console.log(e.target);

export default (props) => (
  const [state, setState] = useState({});

  <button onClick = {clickHandler(state)}>{props.text}</button>
);
Enter fullscreen mode Exit fullscreen mode

That's it, it's that simple! For me I find this is just such a simple way to separate your concerns when using React. It may just be that I'm very bias as I really like functional programming in JavaScript, but I also really enjoy React. I also like to favour simplicity over making a really fancy code base that can do x, y & z, I really like to follow the YAGNI principle. An example being how I've seen people use redux in the most simplistic of React applications, there's no real need & if anything in that kinda scenario in my eyes you're using a bazooka to kill a fly.

But going back to some fundamental topics like writing reusable code, recently when working on making some very accessible web application, I found currying was a God send. Whether that was altering html attributes such as aria-invalid or simply disabling certain buttons from being pressed, etc. When I was writing this application, I was trying to comply with WCAG 2.1 AAA standards, an example being Success Criterion 2.1.3 Keyboard. But back to currying more specifically, it was handy just being able to do something like the following, which could be used across all of my components:

export const handleSomeEnterButton = (expectedCode) => (fn) => (e) => {
  const charCode = e.which ?? e.keyCode;
  if (charCode === expectedCode) {
    fn(e);
  }
};

export const handleEnterButton = (fn) => handleSomeEnterButton(13)(fn);

export const handleSpaceButton = (fn) => handleSomeEnterButton(32)(fn);
Enter fullscreen mode Exit fullscreen mode

I won't blabber on & on unnecessarily, but I'll wrap this up now before I waffle, because I could rant forever! 😂 - But clearly it's not just me that likes the idea of using currying with React, it may be worth reading this post just to get another insight into the subject matter.

Here are a few other posts that may be worth looking at:

  1. Higher order components and currying in React
  2. Currying Functions and React Component Usage
  3. Curry away in React

Discussion

pic
Editor guide