What is the Prop Getters Pattern?
One of the advanced React patterns.
Like every React developer who tends to improve productivity and write code that can be extended more than modified, I’d like to explain prop Getters Pattern.
But Because the majority of React developers prefer functional components, we will write React Component in this style.
So Let’s Go …
What is the Prop Getters Pattern?
Well, we all know that in Javascript all functions are objects. However, functions are built to be more customizable and reusable.
So I’ll try to rely on a simple example which is toggle button, but before we dive into it, let’s make sure we have the right information about first line.
Consider the following:
const object = {name: "Muhammad"}
We create one object with a constant value for the name property, but if we want to customize this object and create another we are forced to do that:
const createObject = value => ({name:value});
// now function can be called multiple times to create other object
const name2 = createObject("Adam");
const name3 = createObject("Youssef");
So, What about our pattern?
Prop getter pattern design is based on function, as mentioned previously functions can be customized therefore, using a prop getter allows for more interesting use cases.
Let’s see the code …
We have a custom hook called useToggle:
This hook will return an object containing isToggle
state, toggle
(function to handle click event), and togglerProps
which is an object that collects all props that I want to pass in the button component.
Then I import useToggle
in the App.js and destruct the object:
We need isToggle
boolean to make a conditional render that can control toggle of elements display.
If you notice I use spread
syntax on line 7 to pass togglerProps
object as props into the button.
Finally, I click on this button. I get:
So How we can improve above code to be more powerful and customizable as you said?
If we convert togglerProps
object to be function and called it getTogglerProps
just for meaningful:
Now, we’ll call this function like a regular function:
And that’s it! The user’s app works just like before.
Wait Wait Wait … “the user’s app works like before!!”
So why do I bother myself??? Well, come with me!
For example, If we have this code from one of your teammates:
<button id="button_1" {...getTogglerProps()}>Click here</button>
Isn’t the ID
part of the button’s props?
Also, Look at this disaster 👇
<button id="button_1" {...getTogglerProps()}>Click here</button>
<button id="button_2" {...getTogglerProps()}>Click meee</button>
<button id="button_3" {...getTogglerProps()}>Click I see 😠</button>
So, How can give freedom and flexibility to add Additional props to the default props collection??
Well, we can pass all values as arguments:
<button {...getTogglerProps({id:"button_1"})}>Click here</button>
Then, let’s update getTogglerProps
function to cater to new props:
If you see we pass props
as a parameter that holds all the custom props
Then spread all custom props into collection props.
Wow!! Did you see it? The ID
passed!!
One step away…
Now, what if the client wanted to pass in a custom onClick
prop?
Like this:
<button
{...getTogglerProps({
id: "button_1",
onClick: () => alert("hello inside button 1")
})}
>
Click here
</button>
ًWhat happened? Isn’t the onClick
handler being updated?
Yes, when you do this you completely override the defaultonClick
handler
because using spread operator will do updates for all toggler
props
Hmm, what we can do?
Actually to solve this problem we want to compose the default handler with the custom onClick
handler so that both of these functions are called.
Look above ☝️ we create excuteFunctions
function that accepts any number of functions then to avoid neglecting the passed arguments we use this spread syntax (...args)
.
So the result:
Yay, we did it 👏 👏 👏.
Conclusion
There are numerous basic and advanced patterns that can be used to create robust, reusable, and adaptable components.
This article was mainly inspired by the amazing work of Kent C. Dodds, who is a famous developer within the React community(https://kentcdodds.com/).
Thank you for reading.
References
React Design Patterns — Prop Getters & Render Props — JavaScriptBit