Declarative Thinking, Pure Functions, and Why React Feels "Different"
If you're learning React, there's a phrase you'll hear almost immediately: React is declarative. Cool. But what does that actually mean?
- •The difference between imperative and declarative programming
- •Why declarative code works: predictability
- •The rules of predictable functions
- •How declarative code + pure functions = React
- •Practical examples of imperative vs declarative code
If you try to look up explanations, you get a definition like:
Imperative programming is how you do something. Declarative programming is what you do.
That sounds profound… once you already understand the difference.
For everyone else, it feels like being told "the chicken came first" when you don't even like eggs in the first place.
Let's fix that.
This article brings together two key ideas:
- Understanding imperative vs declarative programming
- Understanding predictability, side effects, and pure functions
Together, they form the mental foundation that makes React "click."
Imperative vs Declarative: The Real Explanation
Let's start with metaphors — because metaphors work.
Metaphor #1: Red Lobster
You walk into Red Lobster, approach the host stand, and say:
Imperative (HOW)
"I see an open table under the Gone Fishin' sign. We're going to walk over and sit there."
Declarative (WHAT)
"Table for two, please."
Imperative = you describe the steps.
Declarative = you describe the goal, trusting someone else's system to do the steps.
Metaphor #2: Asking for Directions
You call a friend and say: "How do I get to your house from Walmart?"
Imperative
They give you a long list of turns and exits.
Declarative
"My address is 298 West Immutable Alley."
Declarative solutions assume there's an abstraction that already knows the "how."
GPS. The restaurant employee. The automatic transmission in your car.
Declarative systems always hide an imperative engine underneath.
Real-World Declarative Code
Some languages are inherently declarative:
- HTML — you describe structure, not how to draw pixels
<header>
<h1>Declarative Programming</h1>
<p>Sprinkle the word 'declarative' to sound smart</p>
</header>- SQL — you describe what data you want, not how to find it
SELECT * FROM Users WHERE Country="Mexico"You read them and instantly know what's happening.
Imperative JavaScript vs Declarative JavaScript
Let's look at three classic interview-style tasks.
1. Double every number in an array
Imperative
function double(arr) {
let results = [];
for (let i = 0; i < arr.length; i++) {
results.push(arr[i] * 2);
}
return results;
}Declarative
function double(arr) {
return arr.map(item => item * 2);
}2. Sum every number in an array
Imperative
function add(arr) {
let result = 0;
for (let i = 0; i < arr.length; i++) {
result += arr[i];
}
return result;
}Declarative
function add(arr) {
return arr.reduce((a, b) => a + b, 0);
}3. Toggle highlight on a button
Imperative (jQuery/DOM)
$("#btn").click(function () {
$(this).toggleClass("highlight");
$(this).text() === "Add Highlight"
? $(this).text("Remove Highlight")
: $(this).text("Add Highlight");
});Declarative (React)
<Btn onToggleHighlight={handleToggle} highlight={highlight}>
{buttonText}
</Btn>In the declarative version:
- You describe what the UI should look like
- React handles how to update the DOM
- State drives the result
React is declarative because your UI is a function of your state, not a series of manual DOM instructions.
Why Declarative Code Works: Predictability
Let's shift to the second idea — predictability.
As developers, our job is simple:
Make programs predictable.
Every bug ever created came from a mismatch between:
- what the developer expected
- what the program did
Predictable code = fewer surprises = fewer bugs.
So what makes code unpredictable?
Two things:
- Side effects
- Inconsistent outputs
1. Side Effects
A function should take input → produce output.
Anything else is a side effect.
Examples of functions with side effects:
Mutating external state
function addTodo(todo) {
todos.push(todo); // ❌ mutation
}Relying on external state
function calculateFinalPrice(price, qty) {
return price * qty * (1 + TAX_RATE); // ❌ depends on TAX_RATE
}Changing global environment
function updateDocumentTitle(title) {
document.title = title; // ❌ DOM mutation
}Side effects aren't evil — they're just unpredictable.
But when we isolate them, the rest of the program becomes easier to reason about.
2. Inconsistent Outputs
If a function, given the same input, returns different outputs — it's unpredictable.
Examples:
Math.random()Date.now()array.splice()
Even this:
getGithubProfile("user")
Every call returns a different promise.
The Two Rules of Predictable Functions
Rule #1: No Side Effects
A function should not rely on or modify anything outside its scope.
Rule #2: Consistent Outputs
The same input should always return the same output.
These two rules describe what functional programming calls pure functions.
Pure functions are:
- Composable
- Reusable
- Cacheable
- Testable
- Easy to reason about
- Easy to read
They're also the foundation of how React's render cycle works.
Pragmatic Predictability
In the real world, you can't avoid side effects entirely — network requests, DOM updates, localStorage, etc.
But you can contain them.
Example: a pragmatic but still predictable isPrime function with caching:
let primeCache = { 1: false };
const isPrime = (n) => {
if (primeCache[n] !== undefined) return primeCache[n];
for (let i = 2; i <= Math.sqrt(n); i++) {
if (n % i === 0) {
return (primeCache[n] = false);
}
}
return (primeCache[n] = true);
};The impurity is isolated.
Nothing else depends on primeCache.
This is how good abstraction works.
The Big Connection: Declarative Code + Pure Functions = React
React's mental model is built on:
- Describing what the UI should look like
- Using pure functions (components)
- Relying on immutable state
- Avoiding side effects inside render
- Letting React handle the how
A React component is essentially:
UI = f(state)Not:
do this, then change this, then update this…Declarative thinking + predictable functions =
- why React feels easier as apps grow
Summary
Declarative programming isn't magic.
Pure functions aren't academic theory.
They're both tools for one thing:
Maximizing predictability.
When your code is predictable:
- It's easier to test
- It's easier to reuse
- It's easier to change
- It contains fewer bugs
- And your UI layer (React) becomes refreshingly intuitive
This is the mindset shift that makes React "click."