Refactoring React-Native UI using styled-components and pure component patterns
Fairly recently I discovered styled-components as an exciting addition that helps separate display logic from business logic, while improving the over all declarative composition* within each component
*appearing as a set of statements rather than a set of detailed instructions, as will be illustrated through-out this post
Before refactoring:
Lets see an example of a react-native component , that is defined using the available react-native components such as View, Text and Stylesheets for style definitions.
we notice before refactgoring, that the component 1. uses React class to define PageIntro component . 2. Mixes business logic, display logic (additional style pushes) and 3.returns of the set of react-native components with style references passed to it (style={style.container}) . 4. Style references are defined using react-native StyleSheet outside the component , yet in the same file. All in all , it comes to a large file doing a fair few things:
Splitting the conglomerate component into two parts:
each react-native component can be split and defined as a component of two parts:
the 1st part being jsx-like — pure-component (or functional-component) and the 2nd part being css-like — styled-component (css-like)
Lets contain styled-components and pure-components in separate directories for this example. We set the ‘UI’ directory to hold all the presentational (pure) components and the ‘Styled’ directory to contain styled-components — prefixed with Styled<CompName>.js .
In the case of PageIntro.js component in the UI directory, it has the counterpart StyledIntro.js in the Styled directory:
First lets install the styled-components :
npm install styled-components
or
yarn add styled-components
Next, we define the styled-comp for react-native components:
— the StyledIntro.js will hold the definitions of styled-components
— within the StyledIntro.js we import the ‘styled-components’ module and
— use the styled.View, styled.Text to define the looks for the react-native View and Text components.
— set constants for any css attributes and handling of the display logic (see the 2 pictures down)
In the example bellow, you will see Container, StyledLayout*, StyledHeading* and other definitions for Views and Texts that PageIntro.js requires for display.
*it is the practice to prefix styled-components with ‘Styled’ for readability
Display logic handled entirely within the styled-component:
All the display logic that is informed by props (such as type as in this example) can be assessed locally inside the styled-components: the roundness of the button corner based on type prop is assessed and set to border-radius inside the StyledIntro.js, the Container styled-comp.
After Refactoring:
thus far we have:
- switched to pure component pattern instead of the React Class one
- defined display logic separately (inside the styled-comp file) instead of locally inside pure comp.
- imported styled-comps we defined instead of the react-native ones
- kept the components composition mostly declarative as opposed to imperative
And look at the result ! 🤩
Comparing the BEFORE and AFTER of the same comp makes it even more obvious:
I love reading the component now . It is concise and of comfortable size. Readable, inviting easy extension. Hopefully a useful one !