paljakka
Back to all posts

What is Pure Component in React

Published on 2024-09-29

I recently ran into a problem with old code base that was having impure components and i was thinking what the heck is going on during rendering. That file was 1400 lines long, it was tedious project to figure out what is going on.

When writing modern React components we should be using the functional approach. Recently i find out that even React is changing its own documentation from class component approach to functional approach in their new documentation. Learning about pure functions is rather important topic if you are learning functional programming or you are already little bit more experienced developer and are looking for patterns to clean up your code, this might be good approach.

Pure Function

So what is pure function ? In essence, it is a function that returns exactly the same result every time it's called with the same set of arguments. Pure functon has no state, access to external states and no side effects.

Lets take a look at two Javascript array methods slice() and splice(). These two methods do exactly the same thing(kinda), but relatively different approach. Slice is the pure version of these two methods returning every call the same result without mutating the existing array but returning new one everytime. Splice however is mutating the existing array and is causing observable side effects, here is an simple example of mutating, splice is not always returning same output with same arguments:

const listOfNumbers = [1,2,3,4,5]; // No matter how many times you run slice method, // it always return the same result listOfNumbers.slice = (0,4) => [1,2,3,4] listOfNumbers.slice = (0,4) => [1,2,3,4] listOfNumbers.slice = (0,4) => [1,2,3,4] listOfNumbers.splice = (0,4) => [1,2,3,4] listOfNumbers.splice = (0,4) => [5] listOfNumbers.splice = (0,4) => []

Here is the simple function to add person in the list of people. First example is impure. Why? Because it is having side effects by mutating the listOfPeople array outside the function.

const listOfPeople = ['Matt', 'Mike', 'Jack', 'Ann']; // Impure function function addPerson(listOfPeople, person) { listOfPeople.push(person); return listOfPeople; }

Second example with this function is pure, because we are making copy of array of external data and returning that.

const listOfPeople = ["Matt", "Mike", "Jack", "Ann"]; // Pure function function addPerson(listOfPeople, person) { return [...listOfPeople, person] } // you would use function like this addPerson(listOfPeople, "Mark") // and it will return copy of old array // with new name console.log(listOfPeople) => [ "Matt", "Mike", "Jack", "Ann", "Mark" ]

Pure Component

Now you might see wehre we are coming! React design is leaning towards pure function concept. In React rendering have to be pure, always. Components must always return same JSX with same given arguments and should not change any external variables that is existing before rendering.

Example

Here we have simple pure component for rendering Ingredient of recipe application, it is taking two arguments amount, suffix and ingredient. We are not changing anything outside of our component.

export function Ingredient({ amount, ingredient, suffix = '' }) { return ( <p> Add {amount} {suffix} of {ingredient} </p> ); }

Next we add parent for our children(i know clean code would tell you to first define the elephant and then the elephant ears). Here we have recipe of pancake made in a pure component way.

export default function Recipe() { return ( <> <Ingredient amount={1.5} suffix="cups" ingredient="all-purpose flour" /> <Ingredient amount={3.5} suffix="teaspoons" ingredient="baking powder" /> <Ingredient amount={1} suffix="tablespoon" ingredient="white sugar" /> <Ingredient amount={1.25} suffix="cups" ingredient="milk" /> <Ingredient amount={3} suffix="tablespoons" ingredient="butter, melted" /> <Ingredient amount={1} ingredient="egg" /> </> ); }

Conclusion

Pure functions(and pure components) are restrictive but that makes them very easy to test and read. Pure functions should be predictable, like math equation for example 2 x 3 is always 6, that means pure component in functional react should always return same JSX with same arguments you are giving to component. Your component should not manipulate any external data directly. There is places for impure functions but i'm going to return to that later on.