

💡 JSX 작성 시 유의사항
- JSX를 사용한 HTML 구문 작성부는 무조건 최상위 부모태그 하나로 감싸져 있어야 한다.
- 빈태그 <> 가능
// State & Props
import { useState } from "react"
// State lifting up : 상태 끌어올리기
// - 리액트는 부모 컴포넌트가 자식 컴포넌트 상태 변경 불가
// -> 자식에서 발생한 이벤트를 부모에서 처리하도록 하는 상태 끌어올리기 패턴을 이용함
// 해당 파일에서 컴포넌트 총 3개 존재
// Id 컴포넌트(자식)
// Pw 컴포넌트(자식)
// Exam3 컴포넌트(부모) = 해당 파일에서 내보낼 기본 컴포넌트
// Id 컴포넌트(자식)
const Id = (props) => { // 부모에게서 전달받은 속성을 props라고 부름
// *props 꺼내기
const {onChangeId} = props; // props 안에 있는 onChangeId라는 이름의 함수를 이용할 수 있게 됨
//const [id, setId] = useState(""); // 상태(state) 중 'id'를 생성하고 초기값 "" 설정
return (
// JSX를 사용한 HTML 구문 작성부는 무조건 최상위 부모태그 하나로 감싸져 있어야 한다.
<>
<div>
<label>ID : </label>
<input onChange={onChangeId} />
{/* onChange 이벤트에 props 연결 */}
</div>
</>
);
}
// Pw 컴포넌트(자식)
const Pw = ({onChangePw}) => {
// {} 이용하여 props를 바로 꺼내 쓸 수 있음
//const [pw, setPw] = useState(""); // 상태(state) 중 'pw'를 생성하고 초기값 "" 설정
return (
// JSX를 사용한 HTML 구문 작성부는 무조건 최상위 부모태그 하나로 감싸져 있어야 한다.
<>
<div>
<label>PW : </label>
<input onChange={onChangePw}/>
</div>
</>
);
}
// Exam3 컴포넌트(부모)
const Exam3 = () => {
// 자식의 상태를 부모에서 정의(상태 끌어올리기)
const [id, setId] = useState("");
const [pw, setPw] = useState("");
// 자식의 상태를 변경할 수 있는 함수 정의
const onChangeId = e => {
setId(e.target.value);
}
const onChangePw = e=> {
setPw(e.target.value);
}
return(
<>
{/* 컴포넌트 중 Id를 불러 렌더링 (Id가 Exam3의 자식이 됨)*/}
<Id onChangeId={onChangeId}/>
{/* props */}
{/* 컴포넌트 중 Id를 불러 렌더링 (Pw가 Exam3의 자식이 됨)*/}
<Pw onChangePw={onChangePw}/>
<div>
{/* button의 disabled 속성 : 비활성화 속성 (비활성 true / 활성 false)
-> id와 pw 둘 다 작성되어야 활성화
*/}
<button disabled={id.length === 0 || pw.length === 0}>Login</button>
</div>
</>
);
}
export default Exam3;


// State & Props
import { useState } from "react";
// Props Drilling : 상태 내리꽂기
// - props를 통해 데이터를 전달할 때, 자식 컴포넌트에서 필요하지 않은 props를 계속해서 전달하는 행위
// - 코드의 가독성 및 유지보수성 저하
// -> React Context API, Redux 같은 상태 관리 라이브러리를 사용함
// Exam4 > Child1 > Child2 > Child3 > MyComponent 부모자식 관계 연결
// Exam4의 상태값을 MyComponent에서 사용해야 한다면?
// 부모 컴포넌트
function Exam4() {
const [name, setName] = useState("홍길동");
const handleClick = () => {
setName("고길동");
}
return (
<>
<Child1 name={name} />
<button onClick={handleClick}>이름 변경</button>
</>
);
}
function Child1(props) {
return <Child2 name={props.name} />
}
function Child2(props) {
return <Child3 name={props.name} />
}
function Child3(props) {
return <MyComponent name={props.name} />
}
function MyComponent(props) {
// props는 Exam4에서부터 내리꽂기를 통해 전달받은 부모의 상태값
return <h1>{props.name}</h1>
}
export default Exam4;

// props 응용
// 전개 연산자 (...) : 객체 내부의 모든 값을 props로 전달하는 방법
import { useState } from "react";
// 부모
function Exam5() {
const [userData, setUserData] = useState( {name : '홍길동', age : 30} );
//return <MyComponent name={userData.name} age={userData.age} />
return <MyComponent {...userData} />
}
// 자식
function MyComponent(props) {
const { name, age } = props;
const content = `안녕하세요, 제 이름은 ${name}이고, 나이는 ${age}세입니다.`;
return <h3>{content}</h3>
}
export default Exam5;
