react의 component는 하나의 함수를 만들어서 html과 같은 tag들을 반환하는 것을 말한다.
import './App.css'
function App() {
return (
<>
<h1>안녕 리액트</h1>
</>
)
}
export default App
다음과 같이 App
함수는 html tag를 리턴하고 있으므로, 이를 하나의 react component라고 할 수 있다. 또한 함수로 만들어졌으므로 함수형 컴포넌트라고 한다. 클래스로도 가능한데, 클래스 컴포넌트는 old-style이므로 추천하지 않는다.
Header
component를 만들어보도록 하자.
const Header = () => {
return (
<header>
<h1>
heeader
</h1>
</header>
)
}
다음과 같이 arrow function을 사용하여 Header
component를 만들 수 있다.
이제 Header
component를 rendering시켜주도록 하자.
function App() {
return (
<>
<Header/>
<h1>안녕 리액트</h1>
</>
)
}
App
component의 child component로 Header
를 넣어주었다. 이처럼 react component는 부모-자식 component 형식으로 구성된다.
재밌는 것은 Header
는 javascript 함수인데 마치 html tag처럼 사용할 수 있다. 이는 Header
함수를 하나의 react component로 치부하기 때문이다.
react에서는 react component들을 한 곳에 묶어 놓고 관리한다. 따라서 우리의 Header
component도 다른 파일에 관리하도록 하자.
src/components/Header.jsx
를 만들도록 하자.
const Header = () => {
return (
<header>
<h1>
heeader
</h1>
</header>
)
}
export default Header
이제 Header
component를 App.jsx
에서 불러오도록 하자.
import './App.css'
import Header from "./components/Header"
function App() {
return (
<>
<Header/>
<h1>안녕 리액트</h1>
</>
)
}
export default App
import
문으로 불러오면 된다. 아마 python 개발자들은 꽤 헷갈릴텐데 python은 from - import
이지만 여기는 import - from
이다.
Header
component를 만들었으니, Body
component도 만들도록 하자.
function Body() {
return (
<div>
<h1>Body</h1>
</div>
)
}
export default Body
Footer
component도 만들자.
const Footer = () => {
return (
<div>
<h1>Footer</h1>
</div>
)
}
export default Footer
마지막으로 Footer
와 Body
component를 App
component에 써보도록 하자.
import './App.css'
import Header from "./components/Header"
import Body from './components/Body'
import Footer from './components/Footer'
function App() {
return (
<>
<Header/>
<Body/>
<Footer/>
</>
)
}
export default App
이제 나란히 Hader
Body
, Footer
가 렌더링 될 것이다.
function Body() {
return (
<div>
<h1>Body</h1>
</div>
)
}
export default Body
사실 javascript내에서 반환값으로 html tag를 반환하는 것은 불가능한 일이다. 이것이 가능한 일은 jsx문법 덕분이다. 즉, 순수한 js가 아니라 jsx이기 때문이다.
jsx는 javascript + xml 이라는 말로 html과 javascript를 합쳤다라고 생각하면 된다. 다음과 같이 javascript 변수도 렌더링할 수 있는데, {}
를 사용하면 javascript 변수를 사용할 수도 있다.
function Body() {
const number = 10;
return (
<div>
<h1>Body</h1>
<h2>{number}</h2>
</div>
)
}
export default Body
화면에 10이 렌더링 될 것이다.
또한, 덧셈과 같은 계산도 가능하고 삼항 연산자도 가능하다.
function Body() {
const number = 10;
return (
<div>
<h1>Body</h1>
<h2>{number % 2 === 0 ? "짝수" : "홀수"}</h2>
</div>
)
}
export default Body
또한 string
문자열 역시도 넣을 수 있다.
function Body() {
const number = 10;
const hello = "hello"
return (
<div>
<h1>Body</h1>
<h2>{number % 2 === 0 ? "짝수" : "홀수"}</h2>
<h2>{hello}</h2>
</div>
)
}
export default Body
단, jsx
는 문자열, 숫자값만 렌더링이 가능하니 조심하자, 즉 boolean
값을 넣으면 렌더링되지 않는다.
만약, 객체를 넣으면 어떻게될까?
function Body() {
const number = 10;
const hello = "hello"
const obj = {
a: 1,
}
return (
<div>
<h1>Body</h1>
<h2>{number % 2 === 0 ? "짝수" : "홀수"}</h2>
<h2>{hello}</h2>
<h2>{obj}</h2>
</div>
)
}
export default Body
화면에 아무것도 나오지 않을 것이다. 이는 error가 발생했다는 것을 의미한다. 단, object의 property들이 문자열이나 숫자이면 렌더링 된다.
즉 다음과 같이 쓸 수 있다.
function Body() {
const number = 10;
const hello = "hello"
const obj = {
a: 1,
}
return (
<div>
<h1>Body</h1>
<h2>{number % 2 === 0 ? "짝수" : "홀수"}</h2>
<h2>{hello}</h2>
<h2>{obj.a}</h2>
</div>
)
}
export default Body
결론적으로 jsx
에서는 javascript 표현식만 가능하다. 즉, 삼항연산자, 값 자체만 가능하지 다음 처럼 if
문과 같은 것들은 불가능하다.
function Body() {
const number = 10;
const hello = "hello"
const obj = {
a: 1,
}
const func = () => {
return "hello world"
}
return (
<div>
<h1>Body</h1>
<h2>{number % 2 === 0 ? "짝수" : "홀수"}</h2>
<h2>{hello}</h2>
<h2>{obj.a}</h2>
<h2>{func()}</h2>
<h2>{if ...}</h2>
</div>
)
}
export default Body
func
와 같이 javascript함수가 표현식을 리턴한다면 문제가 없지만, if
와 같이 javascript 표현식이 아닌 경우는 실행되지 않는다.
jsx
문법에서는 모든 tag들이 최상위 tag들로 묶여 있어야 한다.
return (
<div>
<h1>Body</h1>
<h2>{number % 2 === 0 ? "짝수" : "홀수"}</h2>
<h2>{hello}</h2>
<h2>{obj.a}</h2>
<h2>{func()}</h2>
<h2>{if ...}</h2>
</div>
)
다음의 예제에서 <div></div>
로 h2
tag들이 모두 묶여 있는 것을 볼 수 있다. div
tag를 없애면 최상위 tag인 <div>
가 없으면 에러가 발생한다. 만약 <div>
와 같이 특정 tag를 최상위 tag로 쓰고 싶지 않다면 <>
를 사용하면 된다.
return (
<>
<h1>Body</h1>
<h2>{number % 2 === 0 ? "짝수" : "홀수"}</h2>
<h2>{hello}</h2>
<h2>{obj.a}</h2>
<h2>{func()}</h2>
<h2>{if ...}</h2>
</>
)
jsx
에서 삼항 연산자를 사용할 수 있다는 것을 알 수 있었다. 삼항 연산자의 결과에는 html tag
들도 넣을 수 있는데, 이를 통해서 렌더링하는 방법을 조건부 렌더링이라고 한다.
function Body() {
const user = {
name: "name",
isLogin: false,
}
return (
<div>
{user.isLogin ?
(<div>마이페이지, 로그아웃</div>) : (<div>로그인</div>)
}
</div>
)
}
export default Body
위와 같이 조건부 렌더링을 통해서 isLogin
이 참이라면 <div>마이페이지, 로그아웃</div>
을 반환하면 아니라면 <div>로그인</div>
을 반환한다.
jsx
로 만든 요소들에 style을 넣어주는 방법에 대해서 알아보도록 하자.
function Body() {
const user = {
name: "name",
isLogin: false,
}
return (
<div style={{ backgroundColor: "green"}}>
<h1>Body</h1>
</div>
)
}
export default Body
주의할 것은 style
에 괄호를 두 번 써주어야 한다는 것과, css처럼 background-color
가 아니라 backgroundColor
와 같이 두번재 단어부터는 소문자를 넣어주는 방법으로 써주어야 한다.
그런데 보통 이렇게 style을 넣어주지 않고 css파일을 따로 만들어준다.
.body {
background-color: red;
border-bottom: 5px solid blue
}
이제 Body.js
에서 Body.css
파일을 import해야한다.
import "./Body.css"
function Body() {
return (
<div className="body">
<h1>Body</h1>
</div>
)
}
export default Body
html tag에 class를 붙여줄 때는 className
을 써준다. 이는 html tag자체에서 class
로 쓰는 것과 약간 다른데, 왜냐하면 class
자체가 이미 js에서 예약어로 쓰이고 있기 때문이다.
react의 component들은 부모-자식 구조를 가진다고 했는데, 부모 component가 자식 component에게 data를 전달하고 싶을 때는 어떻게해야할까?? 이를 위해서 사용하는 것이 바로 props
이다.
먼저 Button component를 만들어보도록 하자.
export default function Button() {
return <button>클릭</button>
}
이제 Body.jsx
에서 불러와보도록 하자.
import "./Body.css"
import Button from "./Button"
function Body() {
return (
<div className="body">
<h1>Body</h1>
<Button/>
<Button/>
<Button/>
</div>
)
}
export default Body
다음으로 Button.css
파일을 만들어 button을 꾸며주도록 하자.
.button {
padding: 10px 20px;
font-weight: bold;
border-radius: 10px;
}
다음으로 Button.jsx
에 button.css
를 반영해보도록 하자.
import './Button.css'
export default function Button() {
return <button className="button">클릭</button>
}
이제 모양이 같은 Button
3개가 나올 것이다. 문제는 이 Button
이 서로 다른 글을 가졌으면 좋겠다. 이 때 사용하는 것이 바로 props
라는 것이다. 바로 부모 component가 자식 component에게 인자를 전달하는 것이다.
import "./Body.css"
import Button from "./Button"
function Body() {
return (
<div className="body">
<h1>Body</h1>
<Button text={"1번 버튼"}/>
<Button text={"2번 버튼"}/>
<Button text={"3번 버튼"}/>
</div>
)
}
export default Body
text
라는 임의의 key값으로 각 Button
의 text가 될 data를 넣어주었다. 이것이 바로 props
이다. 이제 child component인 Button
에서 key인 text
를 가진 props
를 가져와 쓰면 된다.
import './Button.css'
export default function Button(props) {
console.log(props)
return <button className="button">클릭</button>
}
props
라는 object안에 text
라는 key
값으로 부모 component에서 전달한 data를 볼 수 있을 것이다. 이제 props
를 사용하여 button의 text를 렌더링해보도록 하자.
import './Button.css'
export default function Button(props) {
console.log(props)
return <button className="button">{props.text}</button>
}
서로 다른 text
값을 가진 Button component들을 볼 수 있을 것이다. 추가적으로 color
라는 props를 받아와 button의 색깔을 다르게 해주도록 하자.
import "./Body.css"
import Button from "./Button"
function Body() {
return (
<div className="body">
<h1>Body</h1>
<Button text={"1번 버튼"} color={"red"}/>
<Button text={"2번 버튼"}/>
<Button text={"3번 버튼"}/>
</div>
)
}
export default Body
'1번 버튼'에만 color
라는 props를 전달한 것을 볼 수 있다. 이를 style
을 통해 적용시켜보도록 하자.
import './Button.css'
export default function Button(props) {
console.log(props)
return <button className="button" style={{backgroundColor: props.color}}>{props.text}</button>
}
'1번 버튼'만 다른 색깔로 나오는 것을 확인할 수 있을 것이다.
js문법인 구조분해 할당을 통해서 props
들의 property들을 가져올 수도 있다.
import './Button.css'
export default function Button({text, color}) {
return <button className="button" style={{backgroundColor: color}}>{text}</button>
}
또한 props
를 보내주는 parent component에서도 props를 간단하게 보내주는 방법이 있다.
import "./Body.css"
import Button from "./Button"
function Body() {
const buttonProps = {
text: "1번 버튼",
color: "red",
a: 1,
b: 2,
c: 3
}
return (
<div className="body">
<h1>Body</h1>
<Button {...buttonProps}/>
<Button text={"2번 버튼"}/>
<Button text={"3번 버튼"}/>
</div>
)
}
export default Body
사실 별것 없다. buttonProps
라는 object의 property들을 spread문법으로 풀어주는 것이다. 어차피 react component들도 실상은 js object이므로 text
, color
와 같은 key값이 그대로 들어가는 것이다.
props
뿐만 아니라 html
tag들도 전달해줄 수 있는데, 이 경우에는 사용 방법이 약간 다르다.
import "./Body.css"
import Button from "./Button"
function Body() {
const buttonProps = {
text: "1번 버튼",
color: "red",
a: 1,
b: 2,
c: 3
}
return (
<div className="body">
<h1>Body</h1>
<Button {...buttonProps}>
<div>버튼</div>
</Button>
<Button text={"2번 버튼"}/>
<Button text={"3번 버튼"}/>
</div>
)
}
export default Body
첫 번째 button의 child button으로 <div>버튼</div>
을 넣어준 것을 볼 수 있다. 이제 이 child tag를 Button
component에서 어떻게 사용할 수 있는 지 보도록 하자.
import './Button.css'
export default function Button({text, color, children}) {
return (
<button className="button" style={{backgroundColor: color}}>
{children}
</button>
)
}
Body
에서 child로 전달한 html tag는 Button
에서 children
이라는 key값을 통해서 접근이 가능하다. 이를 rendering시켜주기 위해서는 {children}
을 사용하면 된다.
children
에는 html
tag 요소 뿐만 아니라 react component들도 넣을 수 있는데, 다음과 같다.
import "./Body.css"
import Button from "./Button"
function ButtonChild() {
return <div>BUTTON CHILD</div>
}
function Body() {
const buttonProps = {
text: "1번 버튼",
color: "red",
a: 1,
b: 2,
c: 3
}
return (
<div className="body">
<h1>Body</h1>
<Button {...buttonProps}>
<ButtonChild/>
</Button>
<Button text={"2번 버튼"}/>
<Button text={"3번 버튼"}/>
</div>
)
}
export default Body
ButtonChild
component를 Button
component에 넣어주면 Button
component의 children
props에 주입된다.