DEV Community

Cover image for Pure Functions in React
Andrew McKeever
Andrew McKeever

Posted on • Updated on

Pure Functions in React

Motivation

Pure functions are getting thrown around a lot recently, largely due to the popularity of React and its use of pure components. When I first began learning React I knew that pure components always returned the same output given the same input, but I didn't really understand where pure components originated from or their true value. Sure, I had heard "pure components make testing easier" and I would spit out this reasoning in interviews or when speaking to fellow developers, but I didn't truly understand why.

"React will make you a better programmer" was referenced a lot as well in my earlier learnings of React. This sentiment drove my motivation to learn the framework, but it wasn't until I began learning more about functional programming and React's compositional relationship with it that this statement became much more clear.

One of the many parts that React shares with functional programming is the idea of pure functions; components in Reacts case.

What are pure functions?

Pure functions take an input value (a parameter or argument) and depending on that input, produce an output value, that's all. They do one thing only, but they do it well. It should be that whenever you give a pure function the same input it will return the same output every single time.

const myPureFunction = number => return number * 4
Enter fullscreen mode Exit fullscreen mode

You'll likely come across a similar code snippet to the one above if you search across these interwebs of ours for an explanation of pure functions, and for good reason. Functions need to meet a couple of requirements in order to be pure.

Pure functions must

  • Contain no side effects
  • When given the same input, return the same output.

While they're wonderful examples, they don't explain the whole story. For example...

const isThisPure = number => { 
  console.log(number); 
  return number * 4
}
Enter fullscreen mode Exit fullscreen mode

the above function is nearly identical to to our myPureFunction, but this time we've got a nice little console.log() in there, perhaps just to check what we're receiving. While console.log() won't seriously affect our code base, it's still considered a side effect in this function.

Side effects ? Impure : Pure

A side effect is anything that our function mutates that is outside of its scope (our browser's console for example), effecting other parts of our application. Let's look at another example of this.

let globalNumber = 4;

const multiply = (x) => {
  return globalNumber *= x 
}
Enter fullscreen mode Exit fullscreen mode

Here we're updating a variable (globalNumber) which is defined outside of our multiplyByThree function. If we were then to want to access our globalNumber variable later on by another function, but that function was expecting our global variable to be a particular value (e.g a user id) we can see how this will causes issues in the pipeline.

Pure components in React should follow suit and never manipulate global state that other components maybe depending on as well. Pure components should take in props and depending on those props, output a component.

Side effects aren't a bad thing, however. They're quite necessary in nearly all projects, especially in those that update often based on user interaction. Where to put and handle your side effects is the important part to keep your project clear and easy to find any bugs that may occur. State changes in React, for example, are usually left to a few components only or in an entirely separate part of an application.

Return the same value when given the same input value.

The goal of our pure function is to keep our code predictable. To make sure of this, a pure function should return the same output based on the same input; if a function does anything else it's no longer pure.

const multiplyNumber = (x) => {
  return x * 2;
}
Enter fullscreen mode Exit fullscreen mode

Here, we're always going to take in a number and receive that number multiplied by two. This function is incredibly easy to test and reason about. Pure components in React behave in the exact same way; they receive some props and based on those props, return a component. A pure component avoids any use of state.

const HeadlineComponent = props => return <h1>{props.headline}</h1>
Enter fullscreen mode Exit fullscreen mode

Testing components like these are simpler, because we only need to see what's being passed in as props if there's an error. We don't have to check to see where the state is being updated in this component or worry about some sort of logic in our HeadlineComponent incorrectly updating our state; if our headline is wrong, we know it's because the props are wrong.

Conclusion

Function composition laid the foundation for many of the concepts in React, including pure components. Once we understand the principles behind functional programming, we can structure our React code base into a more predictable, testable application. I hope you've come away with a better idea of why pure components exist and how they can make you a better programmer. Feel to provide any feedback and criticisms.

This post is a quick and dirty look into the ideas of functional programming/composition that much greater developers than myself have written about. If you'd like to learn more about functional composition I liked to recommend a few resources that I found really helpful: Alvin Alexander, Fun fun Function, Scotch.io

Top comments (8)

Collapse
 
ckanishka profile image
Kanishka Chowdhury

Nice and concise article.
But I had a doubt, please correct me if am wrong. Here you are trying to reassign a constant variable isn't that invalid?

const globalNumber = 4;

const multiply = (x) => {
  return globalNumber *= x 
}
Collapse
 
keevcodes profile image
Andrew McKeever

I've made the edit. Thanks for finding the typo

Collapse
 
ruslanmystore profile image
ruslan-mystore • Edited

The big question/problem is how to use pure functions in a real-world, complex app.
Here is some small example:

  async function handleMenuItem(groupID: string) {
    await handleGetPosts(null, true, groupID)
    window.scrollTo({
      top: 0,
      behavior: 'smooth',
    })
  }
Enter fullscreen mode Exit fullscreen mode

After clicking a menu item, I need to scroll to top.
This function has a side effect.

What do you think, How to make this one to be a pure function/

Collapse
 
keevcodes profile image
Andrew McKeever

With a React FE, most components should remain pure while leaving only a few components with the responsibility to handle state updates. React context or state management libraries make this concept easier to follow

Collapse
 
vsonmez profile image
Volkan Sönmez

In this case, would it be a correct approach to separate the elements that will make up our screen down to the smallest pieces while developing applications with react?

For example, consider the page header section. There is a page title, a subtitle, three links.

The components we need to create should be title, subtitle, link and a header component that includes them.

Collapse
 
keevcodes profile image
Andrew McKeever

I would say this could be left up to personal taste, but Atomic design takes this exact approach

Collapse
 
niksrj19 profile image
niksrj19

is factorial function is pure function ? if no then
how to convert a factorial function a pure function ?

Collapse
 
keevcodes profile image
Andrew McKeever

It can be depending on the implementation.