DEV Community

Haruto Hirakawa
Haruto Hirakawa

Posted on

2

styled-componentsでラップした複数の子要素に同じpropsを同時に渡す

タイトルの通りです。あるコンポーネント内で配下にある全ての子要素(styled-componentsでラップされたものであるとします)に共通したpropsを渡す場合のやり方の話です。愚直に書いていたらキリがなく最悪なコードが出来上がります。

結論

styled-components/ThemeContext を使おう。

import { ThemeContext } from 'styled-components'
Enter fullscreen mode Exit fullscreen mode

具体例

まずこんな感じの複雑なコンポーネント Component が存在しているとします。多くのコンポーネントやDOMを内包していますが、それらは全てstyled-componentsでラップされています。

const A = styled.div`
  /* ... */
  ${props => props.value}
  /* ... */
`

const B = styled.div`
  /* ... */
  ${props => props.value}
  /* ... */
`

const C = styled.div`
  /* ... */
  ${props => props.value}
  /* ... */
`

// ...

const Z = styled.div`
  /* ... */
  ${props => props.value}
  /* ... */
`

const Component = () => {
  return (
    <Container>
      <A />
      <B />
      <C />
      {/* ... */}
      <Z />
    </Container>
  )
}
Enter fullscreen mode Exit fullscreen mode

ここで、全ての(あるいは殆どの)内包したコンポーネントで value という共通した値を使いまわしたいとします。(この valueuseContext などで更に上層から受け取ったものとします)

そんな時に、こんなこと↓なんてやていられません。

const Component = () => {
  return (
    <Container>
      <A value={value} />
      <B value={value} />
      <C value={value} />
      {/* ... */}
      <Z value={value} />
    </Container>
  )
}
Enter fullscreen mode Exit fullscreen mode

こういうときは ThemeContext を使いましょう、一発で解決します。

const Component = () => {
  return (
    <ThemeContext.Provider value={/* 任意の値 */}>
      <Container>
        <A />
        <B />
        <C />
        {/* ... */}
        <Z />
      </Container>
    </ThemeContext.Provider>
  )
}
Enter fullscreen mode Exit fullscreen mode

ただし、注意点として呼び出す際のpropsのプロパティがthemeになるので、既に違うプロパティで定義してる場合は修正しましょう。

- ${props => props.value}
+ ${props => props.theme}
Enter fullscreen mode Exit fullscreen mode

また当然ではありますがthemeにオブジェクトを渡すことでpropsを一層ラップした状態でこれまで通りに値を扱えます。

interface Attrs {
  // 渡したいpropsの型定義
}

const A = styled.div`
  /* ... */
  ${({ theme: props }: { theme: Attrs }) => props.aaa}
  ${({ theme: props }: { theme: Attrs }) => props.bbb}
  ${({ theme: props }: { theme: Attrs }) => props.ccc}
  /* ... */
`

const Component = () => {
  const attrs: Attrs = { /* ... */ }

  return (
    <ThemeContext.Provider value={attrs}>
      <Container>
        <A />
        <B />
        <C />
        ...
        <Z />
      </Container>
    </ThemeContext.Provider>
  )
}
Enter fullscreen mode Exit fullscreen mode

以上です。

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay