もやもやエンジニア

IT系のネタで思ったことや技術系のネタを備忘録的に綴っていきます。フロント率高め。

Material-uiのstyled-components-apiを使う

今までstyled-componentsmaterial-uiそれぞれ入れて使ってたのですが、material-uiにstyled-componentっぽいAPIが生えてたのに気づいたので使ってみたメモ(キャッチアップできてないだけですね。。。)。@material-ui/coreのバージョンは4.1.0です。

リファレンス

material-ui.com

使ってみる

基本

公式に載ってるコードだとこんな感じですね。本家の方はTemplateStringsArrayでスタイル定義しますが、こちらはデフォルトだとCSSPropertiesのObjectを食わすのでよりJSっぽいスタイルです。

import React from 'react';
import { styled } from '@material-ui/styles';
import Button from '@material-ui/core/Button';

const MyButton = styled(Button)({
  background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
  border: 0,
  borderRadius: 3,
  boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
  color: 'white',
  height: 48,
  padding: '0 30px',
});

MUIのComponentではなく普通のHTMLのタグを指定したいときはstringを指定します。

import React from 'react';
import { styled } from '@material-ui/styles';

const MyButton = styled('button')({
  background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
  border: 0,
  borderRadius: 3,
  boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
  color: 'white',
  height: 48,
  padding: '0 30px',
});

Propsに応じてスタイルを変える

Propsに応じてスタイルを変えたい時はこんな感じです。Componentは必要なPropsを渡せる形にして、スタイルは値ではなくpropsを受け取って値を返す関数を設定します。

import React from 'react';
import { styled } from '@material-ui/styles';

type MyButtonProps = {
  size: 'small' | 'normal';
};

// lintで怒られるの不本意なんですけど・・・
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const MyButton = styled(({ size, ...other }: MyButtonProps) => <button {...other} />)({
  background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
  border: 0,
  borderRadius: 3,
  boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
  color: 'white',
  height: 48,
  padding: '0 30px',
  fontSize: ({ size }: MyButtonProps) => (size === 'small' ? '12px' : '16px'),
});

自分で定義したComponentで使う

classNameをPropsで渡してRootのComponentに渡します。

MyComponent.tsx

import React from 'react';
import { styled } from '@material-ui/styles';

type MyComponentProps = {
  className?: string;
};

const MyComponent = ({ className }: MyComponentProps) => (
  <div className={className}>こんぽーねんと</div>
);

export default MyComponent;

CustomComponent.tsx

import React from 'react';
import { styled } from '@material-ui/styles';
import MyComponent from './MyComponent';

const StyledMyComponent = styled(MyComponent)({
 background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
});

const CustomComponent = () => (
  <div><StyledMyComponent /></div>
);

export default CustomComponent;

おしまい

  • 少し試しただけですが最初から作るならMaterialUIに寄せてもいいかなと思いました。