Advanced
Forwarding Ref
If using React 16.8.0
- 18.3.1
, the withRef
method must be used to pass a ref
down to the underlying DOM element. This uses React's forwardRef
functionality behind the scenes.
import React, { useRef } from 'react';
const Div = styled
.div()
.withRef();
const Button = styled.button();
const Composition = () => {
const divRef = useRef();
const clickHandler = () => {
console.log('divRef', divRef.current);
};
return (
<>
<Div ref={divRef} />
<Button onClick={clickHandler}>
click me!
</Button>
</>
);
};
PropTypes
Built-in typechecking support for React propsTypes. Just chain the withProps
method to an already defined Styled Component and pass the propTypes object as its only argument. This is the same as assigning the propTypes
property on a Component.
import PropTypes from 'prop-types';
type ButtonColour =
| 'blue'
| 'blue'
| 'purple';
type ButtonProps = {
isDisabled?: boolean;
colour?: ButtonColour;
};
const Button = styled
.button<ButtonProps>({
// base button styles
[style.prop('isDisabled')]: {
color: 'light grey',
cursor: 'not-allowed'
},
[style.prop('colour')]: (colour: ButtonColour) => ({
backgroundColor: colour,
borderColour: colour
})
})
.withProps({
isDisabled: PropTypes.bool,
colour: PropTypes.oneOf(['blue', 'green', 'purple'])
});
Server Side Rendering
SSR is supported out of the box, no extra setup required. To get the CSS rendered (including their wrapping style tags), just import and invoke the getStyles
method.
import express from 'express';
import React from 'react';
import { renderToString } from 'react-dom/server';
import { getStyles } from '@n3e/styled';
import App from 'path/to/App';
/**
* @param {string} html
* @param {string} sheets
* @returns {string}
*/
const renderPage = (html, sheets) =>
`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>App: served by express</title>
${sheets}
<script defer src="path/to/script.js"></script>
<head>
<body>
<div id="root">${html}</div>
</body>
</html>`;
const app = express();
app.use((_, res) => {
// render the component to a string
const html = renderToString(<App />);
// get generated styles after component is rendered
const sheets = getStyles();
return res
.status(200)
.contentType('text/html')
.send(renderPage(html, sheets));
});
app.listen('9000');
Experimental
Although Styled works with NextJS, please use with caution as these features have not been finalised.
First, create a component at the root directory, it can be called anything you like.
import { ServerStyles } from '@n3e/styled';
export default async function StyleTags() {
return <ServerStyles />;
}
Then import the component created above and insert it as a child of the head
tag.
import type { Metadata } from 'next';
import StyleTags from './StyleTags';
export const metadata: Metadata = {
// meta data properties
};
type RootLayoutProps = Readonly<{
children?: React.ReactNode;
}>;
export default RootLayout({
children
}: RootLayoutProps) {
return (
<html land='en'>
<head>
<StyleTags />
</head>
<body>
{children}
</body>
</html>
);
}