Twin-Macro on CRA with React 17
Tags: tailwindcss, react, cra, css
Published: 2020-12-24 00:13:52

This recipe is based on this [excellent article](https://dev.to/angelmtztrc/react-app-with-tailwind-css-emotion-twin-macro-3dpe), but with adjustments to make it work with React 17.

* First let’s create a CRA React app:
```sh
npx create-react-app tw-test
```
* Next install all the [Tailwind](https://tailwindcss.com/), [twin.macro](https://github.com/ben-rogerson/twin.macro), and [emotion](https://emotion.sh/docs/introduction) libraries:
```sh
yarn add tailwindcss twin.macro @emotion/core @emotion/styled @emotion/react
```
* Next up, we initialize Tailwind.
```sh
npx tailwindcss init --full
```
This creates a `tailwind.config.js` file in the root directory, which we point to in the `package.json`.
* Add a new babelMacros key to package.json
```json
  "babelMacros": {
    "twin": {
      "config": "tailwind.config.js"
    }
  },

```
You can put the tailwind configuration anywhere you like in the tree, just make sure to specify the path correctly in the `package.json`.
* Import the tailwind CSS into your `index.js` file
```js
import 'tailwindcss/dist/base.min.css';
```
This completes the setup.
# Watch It On YouTube
Another way you can learn about this is to watch the video for this article.
{% youtube ks0Fsn6Csa4 %}
# Using Tailwind
There are several ways to use `twin.macro`, the easiest way is to use the `tw` attribute on any React element, like so:
```jsx
/** @jsxImportSource @emotion/react */
import tw from "twin.macro";

function App() {
  return (
    <div tw="max-w-4xl mx-auto p-5 mt-5">
      <h1 tw="text-blue-500 text-4xl">Hello world</h1>
    </div>
  );
}

export default App;
```
The `@jsxImportSource` syntax is new for React 17. In React 16 the syntax was `@jsx` , if you use that syntax you will get an error message that reads:
```
pragma and pragmaFrag cannot be set when runtime is automatic.
```
## Other Ways To Use Twin-Macro
Other options for twin.macro include creating new React elements in an emotion-styled style, like so:
```jsx
/** @jsxImportSource @emotion/react */
import tw from "twin.macro";

const Heading = tw.h1`text-blue-500 text-2xl p-2`;
const Container = tw.div`max-w-4xl mx-auto p-5 mt-5`;

function App() {
  return (
    <Container>
      <Heading>My custom heading</Heading>
    </Container>
  );
}

export default App;
```
You can also extend these components:
```jsx
/** @jsxImportSource @emotion/react */
import tw from "twin.macro";

const Heading = tw.h1`text-blue-500 text-2xl p-2`;
const BigHeading = tw(Heading)`text-4xl`;
const Container = tw.div`max-w-4xl mx-auto p-5 mt-5`;

function App() {
  return (
    <Container>
      <BigHeading>My big heading</BigHeading>
    </Container>
  );
}

export default App;
```
And you can even do conditional styling:
```jsx
/** @jsxImportSource @emotion/react */
import tw, { styled } from "twin.macro";

const Heading = tw.h1`text-blue-500 text-2xl p-2`;
const MaybeBigHeading = styled(Heading)(({ big }) => [
  big && tw`text-4xl`
]);
const Container = tw.div`max-w-4xl mx-auto p-5 mt-5`;

function App() {
  return (
    <Container>
      <MaybeBigHeading>My custom heading</MaybeBigHeading>
      <MaybeBigHeading big>My big heading</MaybeBigHeading>{" "}
    </Container>
  );
}

export default App;
```
# Next Steps
* Use `yarn build` to create a production deployable version and look at the static asset sizes.
* Use Lighthouse on the production build to check out the performance stats on your application when you build it in production mode. I think you will be impressed.