React children with TypeScript

0. ๋น ๋ฅธ ์š”์•ฝ

React.ReactNode ๋˜๋Š” React.PropsWithChildren<T>๋ฅผ ์‚ฌ์šฉํ•˜์ž.

import React from "react";

interface IProps {
  children: React.ReactNode;
}

const Box = ({ children }: IProps) => {
  return (
    <div>
      <div>Box ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</div>
      {children}
    </div>
  );
};

export default Box;

๋˜๋Š”

interface IProps {
  anyProps: any;
}

const Box = ({ children }: React.PropsWithChildren<IProps>) => {
  return (
    <div>
      <div>Box ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</div>
      {children}
    </div>
  );
};

1. ๊ฐœ์š”

React์˜ props์ค‘ children์€ React์˜ ๊ฐ•๋ ฅํ•œ ํ•ฉ์„ฑ ๋ชจ๋ธ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค. ์—ฌ๊ธฐ์„œ ํ•ฉ์„ฑ์ด๋ผ๋Š” ๊ฒƒ์€ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ด๋Š” ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ๋งŒ ๋ณด๊ณ  ๋„˜์–ด๊ฐ„๋‹ค.

const Box = ({ children }) => {
  return (
    <div>
      <div>Box</div>
      {chldren}
    </div>
  );
};

const Item = () => {
  return (
    <Box>
      <div>Item</div>
    </Box>
  );
};

Item ์ปดํฌ๋„ŒํŠธ๋Š” Box ์ปดํฌ๋„ŒํŠธ์˜ ๋ชจ์–‘์„ ๊ทธ๋Œ€๋กœ ๋‹ด์œผ๋ฉด์„œ Item ์ปดํฌ๋„ŒํŠธ๋งŒ์˜ JSX๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์žˆ๋‹ค. React children์— ๋Œ€ํ•œ ์ถ”๊ฐ€์ ์ธ ์ž์„ธํ•œ ์„ค๋ช…์€ React ํŽ˜์ด์ง€์—์„œ ๋‚˜์ค‘์— ๋‹ค๋ฃจ๋„๋ก ํ•˜๊ณ  ์—ฌ๊ธฐ์„œ๋Š” React children์˜ ํƒ€์ž…์„ ์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ •๋ฆฌํ•œ๋‹ค.

chlidren props์€ ์•„๋ž˜์™€ ๊ฐ™์€ ๋‚ด์šฉ์„ ๋‹ด์„์ง€์— ๋”ฐ๋ผ ํƒ€์ž…์„ ๋‹ค๋ฅด๊ฒŒ ์„ค์ •ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

  • React Element

  • primitive(ex, ๋ฌธ์ž์—ด)

  • ๋ฐฐ์—ด


2. JSX.Element

๊ฐ€์žฅ ์ œํ•œ์ ์ธ ์œ ํ˜•์ด๋‹ค. ๋‹จ์ผ Element์„ ๋‹ด์„ ๋•Œ๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

์•„๋ž˜์˜ ์˜ˆ์‹œ๋ฅผ ์‚ดํŽด๋ณด์ž.

// Box.tsx
interface IProps {
  children: JSX.Element;
}

const Box = ({ children }: IProps) => {
  return (
    <div>
      <div>Box ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</div>
      {children}
    </div>
  );
};

export default Box;

// App.tsx
import Box from "./Box";

function App() {
  return (
    <Box>
      <div>App ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</div>
    </Box>
  );
}

export default App;

App ์ปดํฌ๋„ŒํŠธ๋Š” Box ์ปดํฌ๋„ŒํŠธ์— ๊ฐ์‹ธ์ ธ ์žˆ๋‹ค. ์ฆ‰, App ์ปดํฌ๋„ŒํŠธ๊ฐ€ Box ์ปดํฌ๋„ŒํŠธ์— ๋‹ด์•„์ ธ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‹ด๊ธด App ์ปดํฌ๋„ŒํŠธ์˜ ๋‚ด์šฉ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

<div>App ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</div>

์ด๋ ‡๊ฒŒ ๋‹จ์ผ Element๋ฅผ children์œผ๋กœ ๋‹ด์„ ๋• ์•„๋ž˜์™€ ๊ฐ™์ด children๋ฅผ JSX.Element ํƒ€์ž…์œผ๋กœ ์ง€์ •ํ•œ๋‹ค.

interface IProps {
  children: JSX.Element;
}

2-1. ์˜ค๋ฅ˜ 1) ์—ฌ๋Ÿฌ ๊ฐœ์˜ Element

  • ์˜ค๋ฅ˜ ์ฝ”๋“œ

    import Box from "./Box";
    
    function App() {
      return (
        <Box>
          <div>App ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</div>
          <div>App ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</div>
        </Box>
      );
    }
    export default App;

ํ•˜์ง€๋งŒ ๋‹จ์ผ Element๊ฐ€ ์•„๋‹ˆ๋ผ ์—ฌ๋Ÿฌ ๊ฐœ์˜ Element๊ฐ€ ์žˆ์œผ๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? ๊ทธ๋ ‡๊ฒŒ ๋˜๋ฉด ์•„๋ž˜์˜ ์‚ฌ์ง„๊ณผ ๊ฐ™์€ ์˜ค๋ฅ˜๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

ํ•˜๋‚˜์˜ ์ž์‹์ด ์•„๋‹Œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ž์‹์ด children์œผ๋กœ ์ œ๊ณต๋˜์—ˆ๋‹ค๋Š” ๋‚ด์šฉ์ด๋‹ค. ์ด๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ Element๋ฅผ ํ•˜๋‚˜์˜ ํƒœ๊ทธ๋กœ ๋ฌถ์–ด์ฃผ๋ฉด ํ•ด๊ฒฐ์ด ๊ฐ€๋Šฅํ•œ๋‹ค.(์•„๋ž˜ ์ฝ”๋“œ ์ฐธ๊ณ )

import Box from "./Box";

function App() {
  return (
    <Box>
      <div>
        <div>App ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</div>
        <div>App ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</div>
      </div>
    </Box>
  );
}

export default App;

2-2. ์˜ค๋ฅ˜ 2) string ํƒ€์ž…์˜ Text

  • ์˜ค๋ฅ˜ ์ฝ”๋“œ

    import Box from "./Box";
    
    function App() {
      return <Box>App ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</Box>;
    }
    
    export default App;

์ด๋ฒˆ์—” Element ํƒ€์ž…์˜ children์ด ์•„๋‹ˆ๋ผ string ํƒ€์ž…์˜ children์ด๋ผ๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ. ์•„๋ž˜์™€ ๊ฐ™์€ ์˜ค๋ฅ˜๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.


3. React.ReactChild

React.ReactChild ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ๋ฌธ์ž์—ด ๊ฐ™์€ primitive๋„ children์œผ๋กœ ํ—ˆ์šฉ์ด๋œ๋‹ค.

// Box.tsx
import React from "react";

interface IProps {
  children: React.ReactChild;
}

const Box = ({ children }: IProps) => {
  return (
    <div>
      <div>Box ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</div>
      {children}
    </div>
  );
};

export default Box;

// App.tsx
import Box from "./Box";

function App() {
  return <Box>App ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</Box>;
}

export default App;

// App2.tsx
import Box from "./Box";

function App() {
  return (
    <Box>
      <div>App ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</div>
    </Box>
  );
}

export default App;

3-1. ์˜ค๋ฅ˜ 1) ์—ฌ๋Ÿฌ ๊ฐœ์˜ Element

  • ์˜ค๋ฅ˜ ์ฝ”๋“œ

    import Box from "./Box";
    
    function App() {
      return (
        <Box>
          <div>App ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</div>
          <div>App ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</div>
        </Box>
      );
    }
    
    export default App;

JSX.Element ํƒ€์ž…์„ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์—ฌ๋Ÿฌ๊ฐœ์˜ Element๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.


3-2. ์˜ค๋ฅ˜ 2) Element์™€ Text ํ•จ๊ป˜ ์‚ฌ์šฉ

  • ์˜ค๋ฅ˜ ์ฝ”๋“œ

    import Box from "./Box";
    
    function App() {
      return (
        <Box>
          <div>App ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</div>
          App ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.
        </Box>
      );
    }
    
    export default App;

React.ReactChild์€ ๋‹จ์ผ ์ž์‹๋งŒ ํ—ˆ์šฉ์„ ํ•œ๋‹ค.


3-3. ์˜ค๋ฅ˜ 3) ๋ฐฐ์—ด ์‚ฌ์šฉ

  • ์˜ค๋ฅ˜ ์ฝ”๋“œ

    import Box from "./Box";
    
    function App() {
      return (
        <Box>
          {[1, 2, 3, 4].map((item, index) => (
            <div key={index}>{item}</div>
          ))}
        </Box>
      );
    }
    
    export default App;

children ๋ถ€๋ถ„์— ๋ฐฐ์—ด์„ ์‚ฌ์šฉ์„ ํ•œ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? ์ด๊ฒƒ ๋˜ํ•œ ๊ฐ€๋Šฅํ•˜์ง€ ์•Š๋‹ค.

React.ReactChild ํƒ€์ž…์€ Element[]์˜ ํ˜•ํƒœ์˜ ํƒ€์ž…์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์˜ค๋ฅ˜๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์ด๋Ÿฐ ์˜ค๋ฅ˜๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” children์˜ ํƒ€์ž…์„ React.ReactChild[]๋กœ ๋ฐ”๊พธ์–ด ์ฃผ๋ฉด ๋œ๋‹ค. ํ•ด๋‹น ํƒ€์ž…์€ ์—ฌ๋Ÿฌ๊ฐœ์˜ Element๋ฅผ ํ—ˆ์šฉํ•œ๋‹ค. ๋‹จ Text์™€ Element๋Š” ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.


3-4. ReactChild ํƒ€์ž…์€ ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.

children๋ฅผ React.ReactChild ํƒ€์ž…์œผ๋กœ ์„ค์ •ํ•œ ๊ณณ์„ ๋ณด๋ฉด ReactChild์˜ ๊ฐ€์šด๋ฐ์— ์„ ์ด ๊ทธ์–ด์ ธ ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํƒ€์ž…์ด๋ผ๋Š” ๋œป์ด๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ  ์ด๋Ÿฌํ•œ ํƒ€์ž…์ด ์žˆ์—ˆ๋‹ค๋Š” ๊ฒƒ๋งŒ ์•Œ๊ณ  ๋„˜์–ด๊ฐ€์ž.


4. React.ReactNode

React.ReactNode๋Š” ๋ชจ๋“  ๊ฒƒ์„ ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” ์ตœ๊ฐ•์˜ ํƒ€์ž…์ด๋‹ค. ๋‹จ์ผ Element, ๋‹ค์ˆ˜์˜ Element, ๋ฐฐ์—ด, ๋ฌธ์ž์™€ ๊ฐ™์€ ๊ฒƒ์„ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ  ์„ž์–ด์„œ ์‚ฌ์šฉ ๋˜ํ•œ ๊ฐ€๋Šฅํ•˜๋‹ค.

// Box.tsx
import React from "react";

interface IProps {
  children: React.ReactNode;
}

const Box = ({ children }: IProps) => {
  return (
    <div>
      <div>Box ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</div>
      {children}
    </div>
  );
};

export default Box;

// App.tsx
import Box from "./Box";

function App() {
  return (
    <Box>
      App ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.
      {[1, 2, 3, 4].map((item, index) => (
        <div key={index}>{item}</div>
      ))}
      <div>App ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</div>
    </Box>
  );
}

export default App;

5. React.PropsWithChildren<T>

ํ•ด๋‹น ํƒ€์ž…์€ ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

  1. children ๋ฟ ์•„๋‹ˆ๋ผ ๋‹ค๋ฅธ props๊ฐ€ ์กด์žฌํ•  ๊ฒฝ์šฐ

import React from "react";

interface IProps {
  anyProps: any;
}

const Box = ({ children }: React.PropsWithChildren<IProps>) => {
  return (
    <div>
      <div>Box ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</div>
      {children}
    </div>
  );
};

export default Box;
  1. children ๋งŒ ์กด์žฌํ•  ๊ฒฝ์šฐ

import React from "react";

const Box = ({ children }: React.PropsWithChildren) => {
  return (
    <div>
      <div>Box ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.</div>
      {children}
    </div>
  );
};

export default Box;

React.PropsWithChildren<T> ํƒ€์ž…๋„ React.ReactNode ํƒ€์ž…๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ชจ๋“  ๊ฒƒ์„ ๋‹ด์„ ์ˆ˜ ์žˆ๋‹ค.


5. Conclusion

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋กœ ๋ฆฌ์•กํŠธ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋‹ค ๋ณด๋ฉด ํ•ญ์ƒ ์–ด๋–ค ํƒ€์ž…์„ ์‚ฌ์šฉํ• ์ง€ ๊ตฌ๊ธ€๋กœ ๊ฒ€์ƒ‰์„ ํ•˜๋ฉด์„œ ์ฐพ๋Š”๋‹ค. ๋งค๋ฒˆ ๊ฐ™์€ ๋‚ด์šฉ์ด์ง€๋งŒ ์•„์ง ์ต์ˆ™ํ•˜์ง€ ์•Š์•„ ๊ณ„์† ๊ฐ™์€ ๋‚ด์šฉ์„ ์ฐพ๋Š”๋‹ค. ํžˆ์ง€๋งŒ ์ด๋ ‡๊ฒŒ ๋‚˜๋งŒ์˜ ๊ณต๊ฐ„์— ์ •๋ฆฌ๋ฅผ ํ•˜๊ณ  ๊ณ„์† ์ฐธ๊ณ ํ•ด์„œ ๋ณด๋ฉด ์ฐพ๊ธฐ๋„ ํ›จ์”ฌ ์‰ฝ๊ณ  ์ •๋ฆฌ๊ณ  ์Šค์Šค๋กœ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ๋…์ด ์ž˜ ๋“ค์–ด์˜จ๋‹ค. ๋˜ํ•œ ํ•„์š”ํ•œ ๋‚ด์šฉ์˜ ์ถ”๊ฐ€ ์‚ญ์ œ๋„ ๊ฐ€๋Šฅํ•˜๋‹ˆ ์•ž์œผ๋กœ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์ž์ฃผ ์‚ฌ์šฉ๋˜๊ณ  ์ค‘์š”ํ•œ ๋‚ด์šฉ์„ ์ •๋ฆฌํ•ด์•ผ๊ฒ ๋‹ค. ์ด๋ฒˆ ๊ณต๋ถ€๋ฅผ ํ†ตํ•ด React Children์˜ ํƒ€์ž…์€ React.ReactNode ๋˜๋Š” React.PropsWithChildren<T>๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์„ ํ•˜๊ฒŒ๋˜์—ˆ๋‹ค.


์ฐธ๊ณ 

React Children ๊ณผ ์นœํ•ด์ง€๊ธฐ React children with typescript. ๋ฆฌ์•กํŠธ children ์ปดํฌ๋„ŒํŠธ ํƒ€์ดํ•‘ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ : React.FC๋Š” ๊ทธ๋งŒ! children ํƒ€์ดํ•‘ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ•˜๊ธฐ


๐Ÿ“… 2022-08-23

Last updated