# 🌶️ Currying React Components

# Introduction

If you’ve ever written repetitive or overly verbose React components and felt *"there must be a cleaner way"*, then **currying** might just be your new best friend.

In this article, we’ll explore:

* What currying is (in plain English)
    
* How currying applies to React components
    
* Why this pattern is powerful
    
* Tons of examples (from basic to advanced)
    
* Use-cases and gotchas
    

Let’s dive in! 💡

# 🧠 What is Currying?

In functional programming, **currying** is the process of transforming a function with multiple arguments into a sequence of functions, each taking one argument at a time.

### Traditional Function

```javascript
function greet(greeting, name) {
  return `${greeting}, ${name}`;
}
greet('Hello', 'Alice'); // "Hello, Alice"
```

### Curried Function

```javascript
const greet = (greeting) => (name) => `${greeting}, ${name}`;
greet('Hello')('Alice'); // "Hello, Alice"
```

Why is this useful? Because you can **partially apply** arguments and create **specialized versions** of functions easily.

# 🍱 Currying in React Components

Now let’s translate that concept to React.

### Traditional Component

```javascript
function Button({ variant, size, children }) {
  return <button className={`${variant} ${size}`}>{children}</button>;
}
```

You use it like:

```javascript
<Button variant="primary" size="sm">Click Me</Button>
```

But what if you're always using `variant="primary"` throughout your app? Currying to the rescue.

## 🔁 Currying a Component

### Step 1: Make it a curried function

```javascript
const withVariant = (variant) => (props) => {
  return <Button {...props} variant={variant} />;
};
```

Now you can create a **pre-configured component**:

```javascript
const PrimaryButton = withVariant('primary');

<PrimaryButton size="sm">Click Me</PrimaryButton>
```

✅ DRY (Don't Repeat Yourself)  
✅ Easy to theme  
✅ Improves readability

## 🔧 Real-World Examples

### 1\. ✅ Pre-styled Button Variants

```javascript
const withButtonVariant = (variant) => (size) => ({ children, ...rest }) => (
  <button className={`btn ${variant} ${size}`} {...rest}>
    {children}
  </button>
);

const PrimarySmallButton = withButtonVariant('primary')('sm');
const DangerLargeButton = withButtonVariant('danger')('lg');

<PrimarySmallButton>Save</PrimarySmallButton>
<DangerLargeButton>Delete</DangerLargeButton>
```

### 2\. 🌍 Themed Components (like translation or directionality)

```javascript
const withLang = (lang) => (Component) => (props) => {
  return <Component {...props} lang={lang} />;
};

const Greeting = ({ lang }) => (
  <p>{lang === 'en' ? 'Hello!' : '¡Hola!'}</p>
);

const EnglishGreeting = withLang('en')(Greeting);
const SpanishGreeting = withLang('es')(Greeting);

<EnglishGreeting />
<SpanishGreeting />
```

### 3\. 🧱 Higher-Order Component Factory

Currying also makes it easier to **compose HOCs** in a readable way.

```javascript
const withBorder = (color) => (Component) => (props) => (
  <div style={{ border: `2px solid ${color}` }}>
    <Component {...props} />
  </div>
);

const withPadding = (padding) => (Component) => (props) => (
  <div style={{ padding }}>
    <Component {...props} />
  </div>
);

const Title = ({ children }) => <h1>{children}</h1>;

const StyledTitle = withBorder('blue')(withPadding('20px')(Title));

<StyledTitle>Welcome</StyledTitle>
```

### 4\. 🔁 Conditional Logic

You can even curry for conditional rendering:

```javascript
const withAuth = (isAuthenticated) => (Component) => (props) =>
  isAuthenticated ? <Component {...props} /> : <p>Please log in</p>;

const Dashboard = () => <div>Welcome to the dashboard</div>;

const ProtectedDashboard = withAuth(true)(Dashboard);
```

## 🔄 Currying with Hooks

Currying isn’t just for components—it can work beautifully with hooks too.

```javascript
const useFetcher = (baseURL) => (endpoint) => {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch(`${baseURL}/${endpoint}`)
      .then((res) => res.json())
      .then(setData);
  }, [endpoint]);

  return data;
};

// Usage
const useGitHub = useFetcher('https://api.github.com');
const userData = useGitHub('users/octocat');
```

# ✨ Benefits of Currying React Components

* ✅ **Code Reuse:** Create mini "component factories"
    
* ✅ **Clarity:** Break down logic and props cleanly
    
* ✅ **Partial Application:** Pre-configure components without wrappers
    
* ✅ **Testability:** Smaller units are easier to test
    
* ✅ **Better Theming:** Build dynamic design systems with less code
    

# ⚠️ Gotchas & When *Not* to Curry

* ❌ **Too much abstraction** can make code harder to read for beginners.
    
* ❌ Don’t curry everything—use it when it clearly improves DX (developer experience).
    
* ⚠️ Be careful with props overwriting—always document what’s hardcoded via curry.
    

```javascript
// This will override user's variant prop unintentionally
const CurriedButton = withVariant('primary');

// Be mindful of prop merging priority
```

# 🧪 Advanced Pattern: Currying with Composition Libraries

If you're using libraries like `lodash/fp` or `ramda`, currying becomes even more powerful.

```javascript
import { compose } from 'ramda';

const enhance = compose(
  withBorder('green'),
  withPadding('10px'),
  withLang('en')
);

const EnhancedComponent = enhance(Title);
```

# ✅ Summary

Currying is a **functional pattern** that fits beautifully into React, especially when:

* You want to **pre-configure** a component
    
* You're building **design systems**
    
* You’re composing **HOCs** or **hooks**
    
* You love writing **clean, declarative code**
    

It’s one of those underrated tricks that, once mastered, makes you feel like a React wizard 🧙‍♂️.
