Hints and tips for better programming with the React Native framework
Based on my current experience with the React Native framework, I would like to share with you some hints and tips that will improve your skills in the way you develop with the framework.
Isolate the business logic of your application from the UI/ components code
This is probably the most valuable information someone should have in her mind when developing with React Native. React Native tries to be as platform independent as possible, however, there will be cases, that you will have to write different JavaScript code for iOS and different code for Android.
And how about React on the web? Maybe you want to reuse the code you wrote in your React Native application on a web based version. Always strive to split the logic from the rendering.
Your components have to be so light as possible and every business logic they have to implement have to be placed in other modules/ classes and in files other than the component-files! The components just import these modules/ classes and use their functionality. Apart from that, your business logic should have no knowledge of the React Native framework. Your business code works with the data of your application and it receives them, changes them and delivers them back to UI. The business code has no knowledge of UI components.
By splitting the code this way, you can reuse the business logic, as if it was another JS module in every other application you want. Apart from that you can unit-test this code easier, since the code is free from any UI-specific transactions.
By definition, React Native and React do not have the same standard components. For example React Native uses the <View>
while React uses the standard HTML elements, <div>
in that case. By having light-weight components, you can replace these components with their corresponding with only few clicks.
Create a small and compact UI-library of components
If you find yourself using a combination of components or just a simple “italic” component more than once, then this speaks for a new UI-Control in your UI-library. This methodology supports the reuse of code and you can use these controls is multiple applications.
Decide which data flow path you want to take based on the complexity of your application
We all have done it and for many small projects for a parent-child relationship of components we pass a callback or a state property to the child and doing this way the parent gets alerted when something changes in the child. This type of data management between components works fine when we have to do with a simple relationship between two components. The question is what happens when we have a chain of components, the one inside the other, and we want to pass a state from the first component to the last one.
In such cases we need another architecture for the data flow. Such an architecture should provide an easy way for communication between components without having to form a fuzzy chain of flow. Such an non directional data flow is suggested from the Flux pattern. Currently the two most known frameworks that implement this pattern are Reflux and Redux. Visit their websites to get more information about the advantages of such an approach.
Debugging your React Native application
The main tool you are going to use for debugging your application is the Chrome Debugger. However, as of August 2016, the React Developer Tools do not work when debugging your React Native app. This practically means that you cannot debug the UI-layer (stylings) of your application and thus you cannot experiment with different styles, just like you could do with the web version of your application. For this reason, when we change a style property on the UI, we have to change the code and then build our application either manually or automatically (for example by using a Gulp watcher).
The iOS Simulator provides us an Inspector for inspecting the stylings of the different components and layers in our application. However, we can only check these values, we cannot change them on the fly.
On the JavaScript side the news are good. You can use the Chrome Debugger and from the Sources tab set breakpoints to your code, analyze the call stack or the scope of a variable, and practically do all these tests you would do if you were debugging the JavaScript code of a web application.
Do some “fake” separation of technologies
React Native brings the idea of writing your “CSS”-like stylings in your JavaScript code. Some people may find this features as “a no go” since for many years we learnt that the HTML code belongs to a file with the ending .html, the CSS code to a .css file and the JavaScript code to a .js file. React Native sacrifices the separation of technologies (HTML, JS, CSS) for succeeding a separation of concerns (components).
This practically means that each component should define its own styles by using JavaScript objects. Your CSS code is scattered and used only from the right components and you do not have to define anymore a huge .css file which contains everything and increases the danger that one CSS-rule will override another.
In order to achieve a “fake” separation of technologies, you can split the JavaScript code of the component in one JavaScript file and the styles code in another. Place both of the files inside a folder which has the name of the component. Then you can import the styles into that component.
Avoid performance pitfalls in the UI
Watch out for components that are doing heavy changes on the UI or their state or props properties are being changed, they are being rendered constantly. A UI heavy rendering is for example the UI-code that is generated from a for loop inside a render
method. One example would be the lines of a table. React tries to identify the changes in such cases by searching for unique keys in each row or list element. If these keys are found, only the elements that their content was really changed, are going to be re-rendered.
If you want to push the performance even further, you have to consider of applying lazy loading or memoization techniques to your code, so that the render methods of your components calculate once and then use already-calculated data.
In the React Native documentation you can find more tips about boosting your application’s performance.
Wrapping custom components inside other custom components
When you wrap custom components inside other components, do not forget to use the {this.props.children} expression in the code of the parent component. If you forget to use it, then the child components are not going to be rendered.
TypeScript is your friend
If you use TypeScript instead of JavaScript a best practice is to standardize the state objects of your components with a new type. I prefer using an interface in which I declare all the properties of the state object and then before using the setState()
function, I create an object of this type and pass it to the setState method.