【React】propsのchildrenの基本的な使い方と実例(再利用性の高い部品作成方法)

2022年11月24日React

Reactでコンポーネントを他のコンポーネントに渡せるpropsのchildrenの使い方を紹介します。
childrenを上手に使うことで、再利用性の高いコンポーネントを作成することができます。

childrenの基本的な使い方

他のコンポーネントをラップするコンポーネント(親)

import ChildComp from "./components/ChildComp";
import Container from "./components/Container";

const profile = [
  { name: "yamada", age: 78, country: "KOREA" },
  { name: "suzuki", age: 45, country: "USA" },
];

const Func = () => {
  return (
    <div>
      <Container title="Childrenについて" >
        {'children'}
        <ChildComp {...profile[0]} />
        <ChildComp {...profile[1]} />
      </Container>
    </div>
  );
};

export default Func;

このように、コンポーネントの中にコンポーネントを入れることで、
propsと一緒にコンポーネントもpropsとして渡すことができます。
オブジェクトの配列にすることで、いろいろなデータを出力することが可能になります。

また、childrenは属性として設定することもできます。

const profile = [
  { name: "yamada", age: 78, country: "KOREA" },
  { name: "suzuki", age: 45, country: "USA" },
];

const Func = () => {
  return (
    <div>
      <Container
        title="Childrenについて"
        children={
          [(<ChildComp key={profile[0].name} {...profile[0]} />), (<ChildComp key={profile[1].name} {...profile[1]} />)]
        }
      ></Container>
    </div>
  );
};

export default Func;

その場合、コンポーネントChildCompもJavaScriptのオブジェクトのため、上のようにして渡すことができます。
ただし、この場合はkey属性でユニークな値を指定する必要があります。(指定しないとエラーになります)
よって、上のようにユニークな値のkeyを指定します。

const Container = ({ title, children }) => {
  console.log(children);
  return (
    <div className="container">
      <h3>{title}</h3>
      {children}
    </div>
  );
};

export default Container;

上のように、コンポーネントは、childrenの場所の引数で渡ってくるので、
{}で使うことができます。

childrenとしてラップされる側のコンポーネント(子)

const ChildComp = ({ name, age, country }) => {
  return (
    <div>
      <h3>Name: {name}</h3>
      <p>Age: {age} </p>
      <p>Country: {country} </p>
    </div>
  );
};

export default ChildComp;

こちらは通常と同じです。

渡すコンポーネントの順番を指定する方法

ラップする側の親コンポーネント

import ChildComp from "./components/ChildComp";
import Container from "./components/Container";

const profile = [
  { name: "yamada", age: 78, country: "KOREA" },
  { name: "suzuki", age: 45, country: "USA" },
];

const Func = () => {
  return (
    <div>
      <Container
        title="Childrenについて"
        children={[
          <ChildComp key={profile[0].name} {...profile[0]} />,
          <ChildComp key={profile[1].name} {...profile[1]} />,
        ]}
        zero={<ChildComp key={profile[0].name} {...profile[0]} />}
        first={<ChildComp key={profile[1].name} {...profile[1]} />}
      ></Container>
    </div>
  );
};

export default Func;

コンポーネントの順番を制御したい場合があります。
そのようなときは、上のように、それぞれのコンポーネントにそれぞれの属性をつけることで、可能になります。

ラップされる側の子コンポーネント

const Container = ({ title, children, zero, first }) => {
  console.log(children);
  return (
    <div className="container">
      <h3>{title}</h3>
      {children}
      {first}
      {zero}
    </div>
  );
};

export default Container;

上のようにすることで、{zero}と{first}の順番を入れ替えたりすることで表示させるコンポーネントの順番を制御することができます。

よくある実例-再利用可能なカードコンポーネント

ラップする側の親コンポーネント

import "./card.css";

const Card = ({ children, className, onClick }) => {
  return (
    <article className={`card ${className}`} onClick={onClick}>
      {children}
    </article>
  );
};

export default Card;

上のように、childrenのとかに、classNameを設定しておくと、たとえばaboutページとprofileページで同じカードを使うけど、クラス名だけを変更して再利用可能なコンポーネントとして利用することができます。
また、onClickはない場合は渡ってこないだけなので、onClickがある場合でもない場合上の書き方で問題ありません。

ラップされる側の子コンポーネント

import Card from "../../components/Card";
const data = [
    {id: 1, icon: <Icon1/>, title: 'タイトル1', desc: 'desc1'},
    {id: 2, icon: <Icon2/>, title: 'タイトル2', desc: 'desc2'},
    {id: 3, icon: <Icon3/>, title: 'タイトル3', desc: 'desc3'}
    ]

const About = () => {
  return (
    <section id="about">
      <div className="container about__container">
          <h2>About Me</h2>
          <div className="about__cards">
            {data.map((item) => (
              <Card key={item.id} className="about__card">
                <span className="about__card-icon">{item.icon}</span>
                <h5>{item.title}</h5>
                <small>{item.desc}</small>
              </Card>
            ))}
          </div>
          <p>
            ここに文章
          </p>
          <a href={CV} download className="btn primary">
            ダウンロード
          </a>
        </div>
    </section>
  );
};

export default About;

上のようにCardコンポーネント内で記述されたものがchildrenとして渡されます。
また、CardコンポーネントにclassNameをつけることで、静的な書き方であっても当然propsとしてclassNameが渡されます。
あとは、他のコンポーネントでも同じように、Cardコンポーネント内の記述とclassNameと、必要に応じてonClickを設定してあげれば、
再利用可能なカードコンポーネントになります。

React

Posted by devsakaso