Curso de React | Styled Components

Por 9.99€ al mes tendrás acceso completo a todos los cursos. Sin matrícula ni permanencia.

npm i styled-components

Usaremos el siguiente plugin de visual studio code: vscode-styled-components from Julien Poissonnier

Cuando usamos JSX sin styled-components, los atributos son pasados al DOM obligatoriamente como texto.

En el Visual Studio Code, utilizaría la siguiente extensión para tener autocompletado y coloreado de sintaxis:

vscode-styled-components

Etiquetas anidadas

import { Box } from './styled';
const App = () => <Box><div></div></Box>;
export default App;
import styled from 'styled-components';

export const Box = styled.div`
    background-color: salmon;
    padding: 30px;

    div{
        background-color: palegreen;
        width: 100px;
        height: 100px;
    }
`;

Usando props

Para personalizar el comportamiento de los styled componentes, usaremos siempre props con valores booleanos, con el propósito de no complicar la lógica que va dentro de la definición del styled component.

Estilos en función de props

<Component isRight={true}/>
export const Component = styled.div`
  background-color: ${({ isRight}) => isRight ? 'green' : 'red'};
`;

Atributos en función de props

<Input myMaxLength={2}/>
export const Box = styled.div.attrs({ className: 'pt-3' })``;
export const Input = styled.input.attrs(props => ({
    type: "password",
    maxLength: props.myMaxLength || 5,
    }))`
  color: blue;
`;

Error al usar props

Usando camelCase

Al usar props que utilicen camelCase obtendremos un mensaje de error similar a este:

React does not recognize the `isVisible` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `isvisible` instead. If you accidentally passed it from a parent component, remove it from the DOM element.

Usando booleanos en lugar de textos

El siguiente error da cuando renderizado final llega un booleano en lugar de una cadena de texto.

Received `false` for a non-boolean attribute `editmode`.

Ambos errores se evitan poniendo el símbolo de dolar antes del nombre de la prop. De esta forma, evitamos que la prop se propague al DOM. No te olvides de usar la prop con el símbolo de dolar dentro del styled component.

<MyStyledComponent $isVisible={true} />

Ejercicios styled components

Ejercicio 1.

Crear un styled-component (no un componente funcional de React). Cuando pulsemos sobre un botón, haremos que cambie el color del styled-component que acabamos de crear. Para ello, usaremos un código similar a este:

./src/App.jsx

<button onClick={ () => setColor('red')}>Cambiar color</button>
<MyStyledComponent color={color}/>

Por tanto, tendremos que modificar el código de dos ficheros: App.jsx y styles.js (que contendrá el styled-component).

Ejercicio 2

Crear un componente que usará styled-components y que mostrará un popup cuando reciba una prop visible con el valor true.

Pasos en la resolución:

1. Crearemos un componente llamado Popup que recibirá como props visible y setVisible.

./src/components/Popup.jsx

const Popup = ({visible, setVisible}) => (
   <Back visible={visible} >
      <button onClick={aqui faltan cosas}>Cerrar</button>
   </Back>
);
export default Popup;

2. En dicho componente Popup, tenemos un styled-component <Back> que recibirá una prop booleana y en función de ella se hará visible o invisible.

3. Toda la lógica de visibilidad del componente Popup se gestionará desde el componente App, que tendrá un estado llamado visible. Cuando pulsemos un botón, haremos que el estado cambie y se visualice el popup

./src/App

<button onClick={ () => setVisible(!visible)}>Mostrar popup</button>
<Popup visible={visible}/>

Hacer hover

export const Panel = styled.div`
  background-color: salmon;
  &:hover {
	  background-color: paleGreen
  }
`;

Heredar de otro componente

export const Rectangulo = styled(Cuadrado)`
  width: 200px;
`;

Incrustar código

// El código de BigText debe estar definido antes de ser usado

import styled, { css } from 'styled-components';

const BigText = css`
	font-size: 3rem;
`;

export const RedText = styled.p`
	background: red;
	${BigText};
`;

export const BlueText = styled.p`
	background: blue;
	${BigText}
`;

Añadir animaciones

import styled, { keyframes } from 'styled-components';

const showIt = keyframes`
    to{ opacity: 1}
`;

export const TextPanel = styled.div`
    animation: 5s ${showIt} forwards;
`;

Animaciones con parámetro

En este caso, trataremos la animación como una función:

const statusBarAnimation = (level) => keyframes`
    to{   width: ${level+ '%'}; }
`;

export const StatusBarContainer = styled.div`
        width:0;
        animation: ${({ level }) => statusBarAnimation(level)} 1s forwards;
`;

Para hacer media queries

const desktopStartWidth = 996;

const desktop = `@media (min-width: ${desktopStartWidth}px)`;
const mobile = `@media (max-width: ${desktopStartWidth}px)`;

const Cuadrado = styled.div`
	...
	${mobile} {
		width:100%;
	}
`;

Para maquetar el body

import styled, { createGlobalStyle } from 'styled-components';

export const GlobalStyle = createGlobalStyle`
	body {
		background-color: salmon;
	}
`;
./src/App.js
import { GlobalStyle } from './styles';

const App = () => (
    <div>
      <GlobalStyle />
      <p>App content</p> 
    </div>
);

export default App;

Cargar una tipografía:

Lo haremos usando GlobalStyle:

import font from './assets/fonts/font.ttf';

export const GlobalStyle = createGlobalStyle`
    @font-face {
        font-family: myFont;
        src: url(${font});
    }
`;

Uso de themes

src/App.jsx

import Theme from "./components/Theme";
import { Box } from "./styles";

const App = () => {
    return (
        <Theme>
                <Box />
        </Theme>
    )
}

export default App

src/components/Theme/index.jsx

import { ThemeProvider } from "styled-components";
import { monteserinTheme } from "./themes/monteserinTheme";
import { otroTheme } from "./themes/otroTheme";

const Theme = ({ children }) => {
return (
<ThemeProvider theme={monteserinTheme}>
{children}
</ThemeProvider>
);
};

export default Theme;

src/components/Theme/themes/monteserinTheme.js

export const monteserinTheme = {
  name: "monteserin",
  primaryColor: "red",
};

src/components/Theme/themes/otroTheme.js

export const otroTheme = {
  name: "otro",
  primaryColor: "blue",
};

src/styles.js

import styled, { css } from "styled-components";

export const Box = styled.div`
  background-color: ${({ theme }) => theme.primaryColor};
  width: 100px;
  height: 100px;
  ${({ theme }) =>
    theme.name === "monteserin" &&
    css`
      border-radius: 100%;
    `}
`;

Como estructurar un componente que utiliza styled-components

Curso de React | Styled Components 1
./src/App.js
import Box from './components/box';
const App = () => <Box/>;
export default App;
./src/components/Box/index.js
import Box from './Box';
export default Box;
./src/components/Box/Box.jsx
import { Btn } from './Box.styled';
const Box = () => <Btn onClick="alert('hola)">hola</Btn>;
export default Box;
./src/components/Box/Box.styles.js
import styled from 'styled-components';

export const Btn = styled.button`
    width: 70px;
    height: 70px;
    background-color: pink;
    color: pink;
`;

Enlace a la extensión de Visual Studio Code para generar los componentes de forma automatizada.

Ejercicio

  1. Crear un componente funcional que cargue dos styled components que llamaremos : StyledComponent1 y StyledComponent2.
  2. Debemos usar herencia de styled components. StyledComponent2 debe heredar estilos de StyledComponent1.
  3. Debemos crear un GlobalStyle para dar estilos al body.
  4. Cargaremos una fuente y se la aplicaremos a StyledComponent2.
  5. Debemos tener un efecto hover en StyledComponent2.
  6. StyledComponent2 debe cambiar de tamaño en función de una prop.
  7. Debemos usar media queries.

Por 9.99€ al mes tendrás acceso completo a todos los cursos. Sin matrícula ni permanencia.