<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Performance on Stuart Forrest</title><link>https://www.uglydirtylittlestrawberry.co.uk/tags/performance/</link><description>Recent content in Performance on Stuart Forrest</description><generator>Hugo -- gohugo.io</generator><language>en-uk</language><lastBuildDate>Sat, 13 Jun 2020 16:22:49 +0000</lastBuildDate><atom:link href="https://www.uglydirtylittlestrawberry.co.uk/tags/performance/" rel="self" type="application/rss+xml"/><item><title>Performant rendering and Typescript typings with Wix's React Native Calendar</title><link>https://www.uglydirtylittlestrawberry.co.uk/posts/wix-react-native-calendar-challenges/</link><pubDate>Sat, 13 Jun 2020 16:22:49 +0000</pubDate><guid>https://www.uglydirtylittlestrawberry.co.uk/posts/wix-react-native-calendar-challenges/</guid><description>&lt;h2 id="intro">Intro&lt;/h2>
&lt;p>This post is about some of the challenges I encountered when using Wix&amp;rsquo;s &lt;a href="https://github.com/wix/react-native-calendars">React Native Calendars&lt;/a> library to implement a date picker for an app I was building for a client.&lt;/p>
&lt;p>How and why I chose to use Wix&amp;rsquo;s library over others is a little out scope of this post but I&amp;rsquo;ll say that after having good experiences with some of Wix&amp;rsquo;s other React Native libraries (&lt;a href="https://github.com/wix/react-native-notifications">React Native (Push) Notifications&lt;/a>, &lt;a href="https://github.com/wix/react-native-navigation">React Native Navigation&lt;/a>) I went with their calendar implementation because it appeared flexible, had Typescript typings and a good support process in the issue queue.&lt;/p>
&lt;p>For anybody who lands here doing some discovery on the other options here are what appear to be the main ones:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/stephy/CalendarPicker">Calendar Picker&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/BugiDev/react-native-calendar-strip">React Native Calendar Strip&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/react-native-community/datetimepicker">Datetime Picker&lt;/a> - this actually proxies to the platform standard implementations so a little different&lt;/li>
&lt;/ul>
&lt;p>The challenges I faced using Wix&amp;rsquo;s &lt;a href="https://github.com/wix/react-native-calendars">React Native Calendars&lt;/a> fall into three areas that I will discuss below:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="#typescript-type-definitions">Typescript typings&lt;/a>&lt;/li>
&lt;li>&lt;a href="#custom-day-component">Using custom components&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="what-is-react-native">What is React Native?&lt;/h2>
&lt;p>&lt;a href="https://reactnative.dev">React Native&lt;/a> is a library developed by Facebook to facilitate the use of
&lt;a href="https://reactjs.org/">React&lt;/a> in iOS and Android mobile app development. It doesn&amp;rsquo;t completely preclude the need for
platform (iOS/Android) or languages (Java/Swift/Objective C) specific knowledge but it does provides a React friendly
environment to develop mobile applications predominantly in Javascript.&lt;/p>
&lt;h2 id="typescript-type-definitions">Typescript type definitions&lt;/h2>
&lt;p>&lt;a href="https://www.typescriptlang.org/">Typescript&lt;/a> typings are available from the community via the eminent &lt;a href="https://github.com/DefinitelyTyped/DefinitelyTyped">DefinitelyTyped&lt;/a> project. To use them in your project run one of the following:&lt;/p>
&lt;script src="https://gist.github.com/stuartforrest-infinity/212d191a68e21f1ba5bdfbbbe69fde5d.js">&lt;/script>
&lt;h3 id="a-note-on-community-provided-type-definitions">A note on community provided type definitions&lt;/h3>
&lt;p>This is great news as whilst types for most things can be found that is not always the case. One of the biggest downsides to community provided typings is that they can be out of date as the projects they support continue to evolve or sometimes they are not completely accurate. The consumers of community typings have immense gratitude to the community providing them but there is always work to be done. It is important to highlight here that you can help, if you found typing issues &lt;a href="https://github.com/DefinitelyTyped/DefinitelyTyped#how-can-i-contribute">check out&lt;/a> how to contribute.&lt;/p>
&lt;h3 id="the-problem">The problem&lt;/h3>
&lt;p>The problem with type definitions lies &lt;a href="https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react-native-calendars/index.d.ts#L174">here&lt;/a>. I have extracted this into a gist for ease of reference here.&lt;/p>
&lt;script src="https://gist.github.com/stuartforrest-infinity/153b4f7e5cf69dd81b36613f38422bc6.js">&lt;/script>
&lt;p>React Native Calendars has a lot of features such as marking a multi-day period and marking multiple different events on a particular day, the takeaway is that multiple forms of marking are supported by the DayComponent at the same time. Given that it makes sense that the type definitions specifies an array of data.&lt;/p>
&lt;p>However, the if you choose to use the &lt;code>basic&lt;/code> day component, which is the default, the marking/selected behaviour is &lt;a href="https://github.com/wix/react-native-calendars/blob/master/src/calendar/day/basic/index.js#L49">unexpected&lt;/a>. Given an array of marking data it overrides this with an object with a single &lt;code>marking&lt;/code> property that is effectively meaningless and results in &lt;code>marking/selected&lt;/code> not being applied appropriately. It seems to expect a single instance of a &lt;code>Marking&lt;/code> type as defined in the community types, not an array.&lt;/p>
&lt;h3 id="a-solution">A solution&lt;/h3>
&lt;p>To get around this you when using the &lt;code>basic&lt;/code> day component you need to pass an object of marking data instead of an array as the typing inconsistencies are internal to the library which is not natively typed.&lt;/p>
&lt;h3 id="a-different-solution-if-you-are-using-a-custom-day-component">A different solution if you are using a custom Day component&lt;/h3>
&lt;p>My position was that I had built out most of my implementation using the library but at the very end I realised I would need to use a custom &lt;code>Day&lt;/code> component to achieve the styling our design specs required. That&amp;rsquo;s no problem as the library supports this out of the box. I only really wanted to reimplement the &lt;code>basic&lt;/code> Day component with some layout tweaks I couldn&amp;rsquo;t achieve using the theme overrides. It is a simple component, the library&amp;rsquo;s other &lt;code>Day&lt;/code> components have added complexity to handle multiple &lt;code>marking&lt;/code> types.&lt;/p>
&lt;p>By reimplement, I of course mean &lt;code>copy &amp;amp; paste&lt;/code> and tweak to my needs. This where I encountered the type definition problem above as I was directly using the &lt;code>DayComponentProps&lt;/code> against my custom component.&lt;/p>
&lt;script src="https://gist.github.com/stuartforrest-infinity/01e990f1daddf654a07316008bbfb4b7.js">&lt;/script>
&lt;p>This meant the Typescript build process and my linter was going to be upset because the typings do not support the behaviour of the &lt;code>basic&lt;/code> Day component. This is not allowed:&lt;/p>
&lt;script src="https://gist.github.com/stuartforrest-infinity/07c1153716c82deaa4eb64a4ad7fe256.js">&lt;/script>
&lt;p>Typescript has awesome &lt;a href="https://www.typescriptlang.org/docs/handbook/utility-types.html">Utility Types&lt;/a> that can help here, and help whenever you want to manipulate type definitions. In the gist below you can see that I used &lt;code>Omit&lt;/code> type to selectively redefine only the &lt;code>marking&lt;/code> property of the libraries native type. That&amp;rsquo;s it, problem solved. I could have also handled receiving an array of &lt;code>marking&lt;/code> but there are additional complexities with the community types in that the &lt;code>Marking&lt;/code> type is a &lt;a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html#union-types">Union&lt;/a> of conflicting types. To handle an array would require more &lt;a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types">typeguarding&lt;/a> than I was comfortable with.&lt;/p>
&lt;script src="https://gist.github.com/stuartforrest-infinity/84a16c9254a3eccf85f680395b2e04d1.js">&lt;/script>
&lt;h3 id="where-does-the-problem-lie">Where does the problem lie?&lt;/h3>
&lt;p>I haven&amp;rsquo;t made any PRs about these issues because I&amp;rsquo;m not sure if the problem lies in the type definitions or in the library itself or perhaps a bit of both.&lt;/p>
&lt;h2 id="custom-day-component">Custom Day component&lt;/h2>
&lt;p>I have come to React fairly late in the game and was generally put off by &lt;a href="https://reactjs.org/docs/react-component.html">Class&lt;/a> components. I found their readability and complexity too high or the proliferation of wrapper components trying to avoid that too much of a rabbit hole.&lt;/p>
&lt;p>Now &lt;a href="https://reactjs.org/docs/components-and-props.html">Functional&lt;/a> components I can get on board with, and &lt;a href="https://reactjs.org/docs/hooks-intro.html">hooks&lt;/a> I am really enjoying! Having said that, there is a lot to learn with functional components, I aim to only ever use them but for some of the Class component behaviours it is not always obvious how to replicate them.&lt;/p>
&lt;p>When using a custom &lt;code>Day&lt;/code> component with React Native Calendars you are responsible for handling the &lt;code>shouldComponentUpdate&lt;/code> logic as the library almost exclusively relies on being able to intervene at this lifecycle point to remain performant. Functional components are just function so no lifecycle methods unfortunately&amp;hellip;&lt;/p>
&lt;h3 id="functional-components-componentshouldupdate">Functional components &lt;code>componentShouldUpdate&lt;/code>&lt;/h3>
&lt;p>After a bit of research I found &lt;a href="https://reactjs.org/docs/react-api.html#reactmemo">React.memo&lt;/a>, which isn&amp;rsquo;t exactly the same as the &lt;code>shouldComponentUpdate&lt;/code> lifecycle method but for most use cases it is going to be good enough. It is a HOC that by default compares props, but can also takes an &lt;code>isEqual&lt;/code> func arg to allow you to implement your own comparison logic. As you can see below this can be leveraged to improve the rendering performance of the my custom Day component, for an idea of how much the UI transition between selected and non selected was taking almost a second and now it is immediate.&lt;/p>
&lt;script src="https://gist.github.com/stuartforrest-infinity/186fb422085807fd364356b8f96f56c4.js">&lt;/script>
&lt;h2 id="the-end">The end&lt;/h2>
&lt;p>There is no sample repo/project to go with this post, but the gists above provide the context and some implementations on how the challenges I faced can be resolved.&lt;/p>
&lt;p>I would recommend Wix&amp;rsquo;s React Native libraries, they are some of the most reliable out there. But I must admit they are starting to feel a little dated and I&amp;rsquo;m not sure how much appetite Wix have to keep them up to date with the React ecosystem.&lt;/p>
&lt;h3 id="get-in-contact">Get in contact&lt;/h3>
&lt;p>If you have comments, questions or better ways to do anything that I have discussed in this post then please get in contact via &lt;a href="https://linkedin.com/in/stuart-f-41a43b180">LinkedIn&lt;/a> or &lt;a href="mailto:stuart@uglydirtylittlestrawberry.co.uk">email&lt;/a>.&lt;/p></description></item></channel></rss>