JSX 의 모든 태그는 종료 태그가 필수

적당한 엘리먼트가 없을 경우 <> </> 혹은
<Fragment></Fragment>를 사용
JSX 에서 변수 참조 및 JS 문법은 { } 을 사용

let message = "Hello, React!"
return (
<>
{/* 여기는 주석입니다 */}
<h1>{message}</h1>
//리턴밖에있는 변수 사용하는법
<Welcome/>
</>
);
배열
const item=["안녕하세요","React", "Application입니다."]
return(
<ul>
{/*
<li>{item[0]}</li>
<li>{item[1]}</li>
<li>{item[2]}</li>
*/
}
{/* 배열을 반복해서 li로 변경한다.
map으로 반복을할때 item의 고유값을 줘야한다.*/}
{
item.map((value,index) => <li key={index}>{value}</li>)
}
</ul>
클릭이벤트
const item=["안녕하세요","React", "Application입니다."]
return(
<ul>
{/*
<li>{item[0]}</li>
<li>{item[1]}</li>
<li>{item[2]}</li>
*/
}
{/* 배열을 반복해서 li로 변경한다.
map으로 반복을할때 item의 고유값을 줘야한다.*/}
{
item.map((value,index) =>
<li key={index}
onClick={e=>alert(e.target.innerText)} > {value}</li>)
}
</ul>
);

부모컴포넌트에서 자식 컴포넌트로 읽기전용 데이터 전달
Card.js
import "./Card.css"
export default function Card({name,age,
profileImgSrc="https://cdn-icons-png.flaticon.com/512/2815/2815428.png"}){ //props라는 이름으로 프로퍼티를 받아옴
// console.log(this.props)
// this.props는 클래스 컴포넌트에서만 사용할 수 있다.
console.log(name)
console.log(age)
return(
<div className="card">
<div>{name}</div>
<div>
<img src={profileImgSrc} style={{width:"130px"}}/>
</div>
<div>{age}</div>
</div>
);
}
--------------------------------------------------------------------------app.js
function App() {
return (
// 하나의 컴포넌트는 하나의 태그만 사용가능
<div>
{
//프로퍼티로 전달하는 데이터는
// 문자열은 ""로 전달하고
// 그 외의 모든 데이터는 {}에 작성한다.
}
<Card name="공유" age={27} />
<Card name="조인성" age={27} profileImgSrc="https://entertainimg.kbsmedia.co.kr/cms/uploads/PERSON_20210810081634_aef399d7747a9e97847b080ef3e9ca17.jpg" />
<Card name="강동원" age={27} profileImgSrc="https://i.namu.wiki/i/mqJyzeTqAZUS9f4GzqgNEFcRGiPLyo-DcDKzWbMIAq4Mx7NbEnGdbl75kSClKdDRzsHe5SFyXqNQyk-I_LLJpg.webp" />
<Card name="차은우" age={27} profileImgSrc="https://i.namu.wiki/i/ZnBMAAGJaiFKqDmASXCt-977Xuq6gLA-G8AsD4K1BKCVBEzrjISoW9QyfcSKPnacwuBpCGSSyBtCJv8E-UocNQ.webp" />
</div>
// 그래서 div로 감싸준다.
);
}
-----------------------------------------------수정버전
function App() {
const cardData=[
{name:"공유",age:27},
{name:"조인성",age:27, profileImgSrc:"https://entertainimg.kbsmedia.co.kr/cms/uploads/PERSON_20210810081634_aef399d7747a9e97847b080ef3e9ca17.jpg"},
{name:"강동원",age:27, profileImgSrc:"https://i.namu.wiki/i/mqJyzeTqAZUS9f4GzqgNEFcRGiPLyo-DcDKzWbMIAq4Mx7NbEnGdbl75kSClKdDRzsHe5SFyXqNQyk-I_LLJpg.webp" },
{name:"차은우",age:27, profileImgSrc:"https://mblogthumb-phinf.pstatic.net/MjAyMTA1MTJfMTMg/MDAxNjIwNzk5MzUyMTE4.dU3nDX97OorAThQneUcoHUuw0xgXB9MDFl2WbJB7O2Ug.rKBSgXm8V4XPC0rNm9IMee-3IAmf2QlZ0RLdix8Q5ZYg.JPEG.hwoarangx2/1500610947-1.jpg?type=w800" }
]
return (
// 하나의 컴포넌트는 하나의 태그만 사용가능
<div>
{
//프로퍼티로 전달하는 데이터는
// 문자열은 ""로 전달하고
// 그 외의 모든 데이터는 {}에 작성한다.
}
{
cardData.map((value,index)=><Card key={index}
name={value.name}
age={value.age}
profileImgSrc={value.profileImgSrc}/>)
}
</div>
// 그래서 div로 감싸준다.
);
}

TableApp.js
import Table from "./components/table/Table";
export default function TableApp(){
let content=[
{num: 1,name:"이순신",age:20},
{num: 2,name:"유관순",age:30},
{num: 3,name:"강감찬",age:40},
]
return(
<div>
<Table content={content} />
</div>
);
}
-------------------------------------------------------
Table.js
import Row from "./Row";
export default function Table({content}){
return(
<div>
<table>
<thead>
<tr>
<th>번호</th>
<th>이름</th>
<th>나이</th>
</tr>
</thead>
<tbody>
{
content.map((value,index)=><Row key={index}
name={value.name}
age={value.age}
num={value.num}/>)
}
</tbody>
</table>
</div>
);
}
-----------------------------------------------------Row.js
export default function Row({name, age, num}){
return(
<tr>
<td>{num}</td>
<td>{name}</td>
<td>{age}</td>
</tr>
)
}

export default function Buttons(){
return(
<div>
<button onClick={(event)=>{
console.log(event);
console.log(this);}
}>클릭1</button>
//이렇게 줄 수 없다(카멜케이스로 적어야함)
<button onclick={(event)=>{
console.log(event);
console.log(this);}
}>클릭2</button>

export default function Buttons(){
//버튼이나 div를 클릭했을 때 동작할 함수.
function click(event){
console.log(event.target.innerText)
alert(event.target.innerText+"를 클릭했습니다.")
}
return(
<div>
<button onClick={ (event) =>click(event)}>클릭1</button>
<button onClick={(event)=> click(event)}>클릭2</button>
<button>클릭3</button>
<div>클릭4</div>
</div>
);
}

props 를 이용해 데이터 전달을 했던 것 처럼 이벤트 함수도 props 로 전달이 가능하다

Person.js
export default function Person({id, name,onClickEvent}){
function show(){
alert(name)
}
return(
<div>
<h1 onClick={(e)=> onClickEvent(e.target.innerText,Person) }>{name}</h1>
<p onClick={(e)=> onClickEvent(e.target.innerText,Person)}>{id}</p>
</div>
);
}
--------------------------------------------------------------------------------------------------
PersonApp.js
import PersonList from "./PersonList"
export default function PersonApp(){
const personList=[
{id:1,name:"Kim"},
{id:2,name:"Lee"},
{id:3,name:"Park"},
{id:4,name:"Choi"}
]
return(
<div>
<PersonList personList={personList}/>
</div>
);
}
--------------------------------------------------------------------------------------------------
PersonList.js
import Person from "./Person";
export default function PersonList({personList}){
function itemClick(value, component){
console.log("값: " +value)
console.log("컴포넌트: " +component)
}
return(
<div>
{
personList.map((value,index)=>
<Person key={index}
id={value.id}
name={value.name}
onClickEvent={itemClick}/>)
}
</div>
);
}
컴포넌트가 사용하는 데이터
서버로부터 데이터를 가져와 화면에 구성
데이터가 변경되면 화면이 변경 됨
(State 가 변경되면 View 가 자동으로 갱신됨)
이러한 데이터를 컴포넌트 화면 의 상태 (State) 라고 함
Props 는 부모로 부터 전달되는 불변 데이터
props
state = 컴포넌트 자신이 관리하는 데이터
바뀐 곳만 갱신해준다 화면에
import { useState } from "react"
export default function StepperApp(){
return(
<div>
<Selector/>
</div>
);
}
//컴포넌트 (내부)
function Selector(){
//State: 컴포넌츠가 관리하는 데이터
const [step,setStep]=useState(1)
return(
<div>
<select onChange = { e=> setStep(parseInt(e.target.value))}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<Stepper step={step}/>
</div>
);
}
//컴포넌트(내부)
function Stepper({step}){
const [count, setCount]= useState(0)
return(
<div>
<button onClick={e=> setCount(count-step)}>-</button>
<input type="number" value={count}/>
<button onClick={e=> setCount(count+step)}>+</button>
</div>
);
}