React Native Web #
So far, I have created two libraries for presentational components, one for web and another one for mobile. How good would it be if we had a way to reuse those components for web and mobile? There is, react-native-web offers a way to solve this. I am going to explore it here with an isolated library for presentational components, used, later, by our spa and mobileapplication.
Go to packages folder:
´´´bash
npx tsdx create ui-shared
´´´
Choose react with storybook template.
Update /packages/ui-shared/package.json name:
"name": "@mr/ui-shared",I Remove packages/ui-shared/examples project, since we will be using storybook to see our components working. Also, removed packages/ui-shared/test/blah.test.tsx. It was using some boilerplate code, we will not use.
Add External dependency for react-native-web, react-native and accordingly types. Here react-native-web will only be needed to visualize our components with storybook:
yarn lerna add react-native --scope=@mr/ui-shared --devyarn lerna add react-native-web --scope=@mr/ui-shared --devyarn lerna add @types/react-native --scope=@mr/ui-shared --devLets create our simple BookCard component:
pacakges/ui-shared/src/components/BookCard/index.tsx
import React from 'react';
import { View, Text } from 'react-native';
export default function BookCard({ book }: { book: any }) {
return (
<View>
<Text>{book.title}</Text>
<Text>{book.author}</Text>
<Text>{book.tag}</Text>
</View>
);
}
Again, I am using the book: any. I will fix it later, to use our own IBook type.
Update pacakges/ui-shared/src/index.tsx
import BookCard from './components/BookCard';
export { BookCard };
Storybook #
We want to be able to test and visualize our ui compoments idependently, without needing to have a full application. For That we use storybook:
Removed stories/Things.stories.tsx and created stories/BookCard.stories.tsx for our new component:
import React from 'react';
import { Meta, Story } from '@storybook/react';
import { BookCard } from '../src';
const meta: Meta = {
title: 'BookCard',
component: BookCard,
argTypes: {
book: {
title: 'text',
author: 'text',
tag: 'text',
defaultValue: {
title: "Clean Code", author: 'Uncle Bob', tag: 'software'
}
},
},
parameters: {
controls: { expanded: true },
},
};
export default meta;
const Template: Story = args => ;
// By passing using the Args format for exported stories, you can control the props for a component for reuse in a test
// https://storybook.js.org/docs/react/workflows/unit-testing
export const Default = Template.bind({});
Default.args = {};
And start storybook:
yarn storybook
It will fail because story book is trying to render react-native components on the web. It is here react-native-web enters. For storybook to use react-native-webin place of react-nativewe need to override some webpack configs that will make a link for react-native-web to be used in place of react-native when it is imported.
It is explained here.
I created a file packags/ui-shared/.storybook/webpack.config.js with:
module.exports = async ({ config }) => {
config.resolve.alias = {
'react-native$': 'react-native-web'
};
return config;
};
Now, execute yarn storybook again and it should work, starting a storybook website with a visualization of our BookCard component.
I also removied react-domdependencies, since it is not being used directly:
yarn workspace @mr/ui-shared remove react-dom @types/react-domNext, I will start using ui-shared library on packages/spaand packages/mobile, not needing ui-web and ui-mobile anymore.
Published