Sharing styled-components theme and components between React DOM and React Native: what is the safe boundary?
0 reputation · 15 Apr 2020, 12:21 UTC
0 reputation · 15 Apr 2020, 12:21 UTC
We have a React web app using styled-components and are adding a React Native app using styled-components/native. Both should consume the same design tokens (colors, spacing, typography) through ThemeProvider, and ideally some presentational components would be shared rather than rewritten per platform.
The uncertainty is where the interoperability line actually sits. The web target emits real CSS rules, so pseudo-selectors, media queries, and descendant selectors work there; the native target maps declarations to style objects, so those features presumably cannot carry over. It is also unclear whether helpers like the css utility, attrs, keyframes, and the as prop behave identically across both targets on the same major version, and whether sharing a single component file is realistic or whether only the theme shape and pure helper functions should be shared, with platform-specific styled wrappers behind separate entry points.
Assume a recent major version of styled-components for both targets, with SSR on the web side.
30775 reputation · 15 Apr 2020, 23:08 UTC
The only portable part of styled-components across React DOM and React Native is the ThemeProvider and the plain JavaScript theme object it consumes. All other API surface – component definitions, CSS syntax, runtime helpers – is platform‑specific. Therefore:
{ colors: { primary: '#ff0000' } }) and import it in both projects.styled.div cannot be rendered in React Native, and vice‑versa. Define platform‑specific wrappers (e.g. Button.web.js and Button.native.js) and expose a single name via Platform.select.css, attrs, as prop, and transient props ($$) are available in both packages, but features that rely on CSS pseudo‑selectors, media queries, or descendant selectors are only functional on the web. keyframes is a no‑op in the native package.ServerStyleSheet and other SSR APIs exist only in the web package.Styled‑components ships two distinct runtimes: styled-components for the browser and styled-components/native for React Native. Each runtime implements the same public API surface, but the underlying rendering engine differs. The ThemeProvider uses React context, which is identical on both platforms, so a shared theme object is safe. However, component definitions are tied to the underlying element type (<div>, <View>, etc.) and to CSS parsing. Mixing imports or attempting to render a web component in a native app throws a runtime error.
When sharing helper functions that do not import styled (e.g. token utilities, color helpers), you can keep them in a common module and import them wherever needed. Avoid importing styled or css from the web package into a native project.
styled-components/native package. Ensure you install the correct dependency for each target.ServerStyleSheet is web‑only. Using it in a native bundle will throw a ReferenceError.StyleSheet directly, so any Stylis‑specific features (e.g. nested selectors) are unavailable on native.theme.js exporting a plain object:export default {
colors: { primary: '#0066ff', secondary: '#ff6600' },
spacing: { sm: 8, md: 16, lg: 24 },
typography: { h1: { fontSize: 32 } },
};<ThemeProvider theme={theme}> from styled-components.<ThemeProvider theme={theme}> from styled-components/native.Button.web.js and Button.native.js) and expose a single name via Platform.select in an index.js.colorHelpers.js) that do not import styled from either package.Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.