--- Update 2021-05-03 (one month later)
Chakra UI has just announced they will be coming to Native "pretty soon"!
--- (original blog post below)
This post grew out of the discussion on the React Native issue for Chakra UI, plus my own research. I fear some of the brief points @steida made on the issue were lost to some, as they were to me, so I decided to write a bit more thoroughly on them.
First, a primer on React Native Web (RNW), for those unfamiliar. RNW is taking the high-level API of React Native, onto the Web. "Why not just use React?", you say. RNW is all about using specifically tailored native cross-platform components (that primarily render onto a native Screen view) and also rendering them on the web (to the DOM). Which is possible because RN/RNW uses higher-level abstractions (
<Text> instead of
<span>, etc.). (RNW should have been called "React Platform", really.)
You can't use Chakra UI with React Native or React Native Web, since they already have styling baked in.
said, React Native Web (RNW) has its own fully integrated styling solution, StyleSheet, which has its own API.
The StyleSheet solution comes from RN, naturally. But on web, with RNW, it needs some justification. Why not simply use any other stylesheet solution? In short: To have a uniform styling API across RN and RNW. But there are other benefits too, like working with a higher-level abstraction:
React Native Web abstracts away the complexities of CSS. CSS allows 3 ways of styling, which make it complex (unless you “own the whole stack”, like RN and RNW):
- statically (css file; cacheable and fast)
- dynamic runtime styling (props object or inline styles; flexible)
- escape hatch styling (hooking into DOM nodes outside of React; typically used for animations).
“The React-DOM ecosystem doesn’t have a foundation upon which everything else is built. So, in RN if you install a RN package, then (pretty much) everything is using the same style library, using the same measurements etc. so it can interop at this quite broad level.” - Nicolas Gallagher, RNW creator, at 29:00 in this 2018 podcast
So React Native has its own fully integrated props based styling API. Thus, integrating Chakra UI with RN/RNW could be particularly challenging, because you risk losing that high level styling API which RN/RNW are all about. That's also why you don't want to use an extra CSS-in-JS library like styled-components or emotionjs on top of RNW, like @steida expressed. (I don't think people still attempt to do that because they dislike the RNW solution, or prefer string interpolation instead of RNW's StyleSheet. They are just confused, like I was, and think they need a styling solution with RN/RNW, when in reality it is already baked in.)
So you can't currently use Chakra UI out of the box with React Native.
Neither would you want to do it in RNW, because of RNW's high level API. RNW is not meant for using a component library made for web, such as Chakra UI, on native. To do that, while also getting the cross-platform benefits of RNW, then Chakra UI would have to be rewritten from the bottom-up with those higher-level abstractions in mind (
<View> instead of
<div> etc., and with StyleSheet instead of styled-system and emotion under the hood). This is not likely to happen. The issue has not had much progress since Oct 2019, and was closed in Apr 2020.
It's probably better to use Chakra UI where it shines: on the web. Many websites and webapps don't need to be native, after all. Going for RN or RNW for them would be pure overhead (even though Expo Web has done great things to reduce that overhead..).
In the TypeScript implementation, I'm extracting most of the component logic into hooks so it can be consumed in React Native Web and React (Web). Perhaps, it might help. - segundeadebayo, Chakra UI creator
But, as said, integrating Chakra UI with RNW wouldn't be particularly desirable, because you'd lose that high level API which RNW is all about. So it defeats the point of using RNW at all.
And unless you want to make a mobile app that exposes a WebView and loads in a webpage with ChakraUI on it.
Though you could use RN to make a native wrapper/shell app that exposes a WebView in which you load your webapp that uses Chakra UI, of course.
But then you would have to write your own bridge to communicate between your native app and your webapp (at least until Basecamp open sources their bridge for that, Hotwire Strada, later this year). You might be able to write the native app in React Native, and communicate with the webapp through the WebView, but this is hacky, and I'd rather rely on a proper bridge of some sorts.
NB: This type of bridge is not the same as RN's own bridge which is between the RN app and the native platform.
Capacitor, as an alternative to RN, is the only solution I know of that will easily give you a single direct bridge between your webapp and the native platform (think 'Electron for mobile'). Read more on Capacitor at the end of this post.
If you want to use RN/RNW and want to use a component library like Chakra UI, then you have two good alternatives, to my knowledge. Especially if you want to use NextJS to do Server-Side Rendering (SSR) of the webapp/PWA.
Here is a comparison of Magnus UI vs Dripsy.
So if you want to use RN/RNW then either of these seems the way to go, instead of using Chakra UI.
But if you are determined to use Chakra UI on mobile, and are willing to sacrifice using RN/RNW, there is another option.
Instead of using React Native (RN), a different option to get to use Chakra UI on mobile (and other platforms) would be to use Capacitor, which is a native runtime/bridge for webapps (think 'Electron for mobile').
Because Capacitor provides a native runtime environment for web apps, that means it can be used to turn any React web app into a native app. So apps using Material-UI or Chakra or Prime or Ant or Ionic Framework, or any other React UI library, can be turned into native apps using Capacitor (see our examples repo for real code in a variety of libraries).
This simply isn’t possible with React Native. Most popular React UI libraries target the web and react-dom, and most web libraries use web technologies like CSS that aren’t supported in React Native (at least not in their native format)
NB: Using Capacitor in practise means bundling your website inside the app, NOT loading it on demand (via a url). That is the recommended option from Capacitor’s creator Max Lynch, since if not: "Apple will likely reject your app since it is not “self-contained.". To make it self-contained, you can do a NextJS static export, for example. Sadly, for distribution, this means going through the App Store process, and asking clients to update their app for every code change (many will thus be out of date). Unless you use a service such as CodePush for Capacitor. Never mind the weirdness of using a code distribution tool for native apps, just to serve users with fresh HTML, CSS and JS...
Correct me if I'm wrong in any of this. This is at least what my research has turned up. Hope it helps someone.
Feel free to share alternative solutions or general approaches in the comments.