This post is about some of the challenges I encountered when using Wix’s React Native Calendars library to implement a date picker for an app I was building for a client.
How and why I chose to use Wix’s library over others is a little out scope of this post but I’ll say that after having good experiences with some of Wix’s other React Native libraries (React Native (Push) Notifications, React Native Navigation) I went with their calendar implementation because it appeared flexible, had Typescript typings and a good support process in the issue queue.
For anybody who lands here doing some discovery on the other options here are what appear to be the main ones:
- Calendar Picker
- React Native Calendar Strip
- Datetime Picker - this actually proxies to the platform standard implementations so a little different
The challenges I faced using Wix’s React Native Calendars fall into three areas that I will discuss below:
What is React Native?
Typescript type definitions
A note on community provided type definitions
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 check out how to contribute.
The problem with type definitions lies here. I have extracted this into a gist for ease of reference here.
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.
However, the if you choose to use the
basic day component, which is the default, the marking/selected behaviour is unexpected. Given an array of marking data it overrides this with an object with a single
marking property that is effectively meaningless and results in
marking/selected not being applied appropriately. It seems to expect a single instance of a
Marking type as defined in the community types, not an array.
To get around this you when using the
basic 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.
A different solution if you are using a custom Day component
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
Day component to achieve the styling our design specs required. That’s no problem as the library supports this out of the box. I only really wanted to reimplement the
basic Day component with some layout tweaks I couldn’t achieve using the theme overrides. It is a simple component, the library’s other
Day components have added complexity to handle multiple
By reimplement, I of course mean
copy & paste and tweak to my needs. This where I encountered the type definition problem above as I was directly using the
DayComponentProps against my custom component.
This meant the Typescript build process and my linter was going to be upset because the typings do not support the behaviour of the
basic Day component. This is not allowed:
Typescript has awesome Utility Types that can help here, and help whenever you want to manipulate type definitions. In the gist below you can see that I used
Omit type to selectively redefine only the
marking property of the libraries native type. That’s it, problem solved. I could have also handled receiving an array of
marking but there are additional complexities with the community types in that the
Marking type is a Union of conflicting types. To handle an array would require more typeguarding than I was comfortable with.
Where does the problem lie?
I haven’t made any PRs about these issues because I’m not sure if the problem lies in the type definitions or in the library itself or perhaps a bit of both.
Custom Day component
I have come to React fairly late in the game and was generally put off by Class 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.
Now Functional components I can get on board with, and hooks 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.
When using a custom
Day component with React Native Calendars you are responsible for handling the
shouldComponentUpdate 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…
After a bit of research I found React.memo, which isn’t exactly the same as the
shouldComponentUpdate 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
isEqual 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.
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.
I would recommend Wix’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’m not sure how much appetite Wix have to keep them up to date with the React ecosystem.
Get in contact
If you have comments, questions or better ways to do anything that I have discussed in this post then please get in contact.