Props & State
💻 Props (Properties)
- 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달하는 방법 (상위➡️하위 만 가능!)
- 여러 번 쓰이는 컴포넌트에서 내부 데이터만 다르게 사용하고 싶을 때 사용
- 컴포넌트끼리 값을 전달하는 수단
// Class형 props
import { Component } from "react";
// props는 반드시 객체이다.
class ClassProps extends Component {
render() {
const divStyle = {
color: this.props.color,
};
return (
<div style={divStyle}>
<h4>hi, {this.props.name}</h4>
<ul>
<li>별명: {this.props.nickname}</li>
<li>좋아하는 색: {this.props.color}</li>
</ul>
</div>
);
}
}
class ClassProps2 extends Component {
render() {
const { name, color, nickname, fontColor } = this.props;
const divStyle = {
color: fontColor,
backgroundColor: color,
};
return (
<div style={divStyle}>
<h4>hi, {name}</h4>
<ul>
<li>별명: {nickname}</li>
<li>좋아하는 색: {color}</li>
</ul>
</div>
);
}
}
ClassProps2.defaultProps = { fontColor: "beige" };
export { ClassProps, ClassProps2 }; // 여러개를 내보낼때는 객체 형태로 보내야 한다.
💻 State
- 컴포넌트 내부에서 관리되는 변경 가능한 데이터
- 가변성!
// Class형 state
import { Component } from "react";
export default class ClassState extends Component {
// Class 형에서는 state가 객체형으로 관리 된다.
// render() 함수 위에서 state 선언
state = {
banana: "바나나",
};
render() {
const { banana } = this.state;
return (
<div>
<p>{banana}</p>
<button
onClick={() => {
this.setState({ banana: "banana" });
}}
>
영어로 변경! (Class 형)
</button>
</div>
);
}
}
Event Handling
💻 Synthethic Event (합성 이벤트)
export default function SyntheticEvent() {
function syntheticEvent(e) {
console.log(e);
console.log("합성 이벤트 클릭");
}
function printInput(e) {
console.log(e.target.value);
}
function callTest() {
alert("안녕하세요?");
}
return (
<div>
<button onClick={syntheticEvent}>콘솔을 보세요</button>
<button onClick={callTest()}>함수 호출해서 전달</button>
<br />
<input
type="text"
placeholder="글자를 입력 하세요."
onChange={(e) => {
printInput(e);
}}
/>
</div>
);
}
map()
- 배열 데이터를 좀 더 효율적으로 사용하기 위해 map 사용!
import { useState } from "react";
export default function MapPrac() {
const [list, setList] = useState([
{ id: "1", name: "코디", email: "codi@gmail.com" },
{ id: "2", name: "포터", email: "harrypotter@gmail.com" },
]);
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const addUser = () => {
const newList = list.concat({
id: list.length == 0 ? 1 : list[list.length - 1].id + 1,
name: name,
email: email,
});
setList(newList);
setName("");
setEmail("");
};
// 더블클릭 삭제
const deleteUser = (id) => {
const newUser = list.filter((name) => {
return name.id !== id;
});
setList(newUser);
};
// 엔터로 입력
const enterInput = (e) => {
if (e.key == "Enter") {
addUser();
}
};
return (
<>
<input
type="text"
placeholder="이름"
value={name}
onChange={(e) => {
setName(e.target.value);
}}
/>
<input
type="text"
placeholder="이메일"
value={email}
onDoubleClick={deleteUser}
onChange={(e) => {
setEmail(e.target.value);
}}
onKeyDown={enterInput}
/>
<button onClick={addUser}>등록</button>
<ul>
{list.map((el) => {
return (
<li
onDoubleClick={() => deleteUser(el.id)}
style={{ fontWeight: 700 }}
>
{el.name}: {el.email}
</li>
);
})}
</ul>
</>
);
}
filter()
- filter()의 인자로 넘겨지는 callback함수의 테스트(조건)를 통과하는 요소를 모아 새로운 배열을 생성
- 배열에서 원하는 값을 삭제하는 코드 구현 가능
import { useState } from "react";
export default function Alphabet() {
const [list, setList] = useState([
{ id: 1, alphabet: "a" },
{ id: 2, alphabet: "b" },
{ id: 3, alphabet: "c" },
{ id: 4, alphabet: "d" },
{ id: 5, alphabet: "e" },
]);
const [input, setInput] = useState("");
const addAlphabet = () => {
const newList = list.concat({
id: list.length == 0 ? 1 : list[list.length - 1].id + 1,
alphabet: input,
});
setList(newList);
setInput("");
};
// input 태그에 대고 엔터를 눌렀을 때 등록이 되도록
const activeEnter = (e) => {
// console.log(e.key); // 키보드의 정보
if (e.key == "Enter") {
addAlphabet();
}
};
// 해당 태그에 더블클릭을 했을 때 삭제 되도록
const deleteAlphabet = (id) => {
const newAlphabet = list.filter((alphabet) => {
return alphabet.id !== id;
});
setList(newAlphabet);
};
return (
<div>
<h2>alphabet</h2>
<input
type="text"
value={input}
onChange={(e) => {
setInput(e.target.value);
}}
onKeyDown={activeEnter}
onDoubleClick={deleteAlphabet}
/>
<button onClick={addAlphabet}>추가</button>
<ol>
{list.map((el) => {
return (
<li key={el.id} onDoubleClick={() => deleteAlphabet(el.id)}>
{el.alphabet}
</li>
);
})}
</ol>
</div>
);
}
Life Cycle
💻 생명주기
1. 생성(Mounting)
- constructor: 컴포넌트가 생성될 때 가장 먼저 실행되는 메서드로, 초기 state를 설정할 수 있다.
- render: 컴포넌트를 렌더링하는 가장 중요한 메서드
- componentDidMount: 컴포넌트가 처음 렌더링된 후 실행되며, DOM 조작이나 데이터 요청 등을 수행
2. 업데이트(Updating)
- getDerivedStateFromProps: props나 state의 변경을 감지하고 state를 업데이트
- shouldComponentUpdate: 컴포넌트의 리렌더링 여부를 결정
- render: 변경된 내용을 반영하여 다시 렌더링
- componentDidUpdate: 컴포넌트 업데이트가 완료된 후 실행
3. 제거(Unmounting)
- componentWillUnmount: 컴포넌트가 DOM에서 제거되기 전에 호출되며, 타이머 제거나 네트워크 요청 취소 등의 정리 작업을 수행
import { Component } from "react";
class MyComponent extends Component {
// 마운트되었을 때 동작
componentDidMount() {
console.log("mount 되었어요!!🐛");
}
// 업데이트되었을 때 동작
componentDidUpdate() {
console.log("update 되었어요!!🔥");
}
// 언마운트 되기 직전
componentWillUnmount() {
console.log("unmount 됩니다!!✨");
}
render() {
return <p>MyComponent {this.props.number}</p>;
}
}
class LifeCycleClass extends Component {
state = {
number: 0,
visible: true,
};
changeNumberState = () => {
this.setState({ number: this.state.number + 1 });
};
changeVisibleState = () => {
this.setState({ visible: !this.state.visible });
};
render() {
return (
<>
<button onClick={this.changeNumberState}>PLUS</button>
<button onClick={this.changeVisibleState}>On/Off</button>
{/*
- visible state 값에 따라서 MyComponent 가 생성및 제거됨
- 생성(mount) , 제거(unmount)
*/}
{this.state.visible && <MyComponent number={this.state.number} />}
</>
);
}
}
export default LifeCycleClass;
🤔 실습오답
🍎 Select.js
- 내용 부분이 안뜨는게 Result.js에서 {content}를 불러오지 않아서 였다.
// Select.js
export default function Select({ setData }) {
/**
* { fruit: "apple",
background: "white",
color: "gray",
content: "text", }
*
*/
return (
<div>
{/* {select 3개} */}
과일:{" "}
<select
onChange={(e) => {
// console.log("target", e.target);
// console.log("current", e.currentTarget);
// console.log("current", e.target.value);
setData((prevState) => {
return { ...prevState, fruit: e.target.value };
});
}}
>
<option value="apple">사과</option>
<option value="grape">포도</option>
<option value="peach">복숭아</option>
<option value="banana">바나나</option>
</select>
배경색:
<select
onChange={(e) => {
setData((prevState) => {
return { ...prevState, background: e.target.value };
});
}}
>
<option value="black">black</option>
<option value="white">white</option>
<option value="red">red</option>
<option value="blue">blue</option>
<option value="green">green</option>
<option value="yellow">yellow</option>
<option value="pink">pink</option>
</select>
글자색:
<select
onChange={(e) => {
const color = e.target.value;
setData((prevState) => {
return { ...prevState, color };
});
}}
>
<option value="black">black</option>
<option value="white">white</option>
<option value="red">red</option>
<option value="blue">blue</option>
<option value="green">green</option>
<option value="yellow">yellow</option>
<option value="pink">pink</option>
</select>
</div>
);
}
// Result.js
export default function Result(props) {
const { content, fruit, color, background } = props.data;
// console.log("data", data); // Object
return (
<div>
<img src={`/${fruit}.jpg`} width={100} height={100} />
{/* 백틱을 넣는 것 또한 JS 문법이므로 중괄호로 감싼다 */}
<p
style={{
backgroundColor: background,
color: color,
width: "100px",
height: "30px",
textAlign: "center",
lineHeight: "30px",
}}
>
{content} << 이 부분이 문제였다.
</p>
</div>
);
}
📓 MapPrac2.js
- 사소한 실수였다. button에 type을 넣지 않아서 내용을 입력하면 자동으로 새로고침이 되었었다.🥲
<button type="button" onClick={addContent}>
작성
</button>
type="button" 을 안넣어서...
// MapPrac2.js
import { useState } from "react";
export default function MapPrac2() {
const [comment, setComment] = useState([
{
writer: "승철",
title: "화이팅",
},
{
writer: "정한",
title: "하니해",
},
{
writer: "지수",
title: "화이팅",
},
]);
const [inputTitle, setTitle] = useState(""); // 제목 등록 input
const [inputWriter, setWriter] = useState(""); // 작성자 등록 input
const [inputSearch, setInputSearch] = useState(""); // 검색어 input
const [result, setResult] = useState([]); // 검색결과에 대한 배열
const [searchType, setSearchType] = useState("writer");
const addContent = () => {
let newComment = {
writer: inputWriter,
title: inputTitle,
};
setComment([...comment, newComment]);
setTitle("");
setWriter("");
};
// 검색을 실행하는 함수
const searchComment = () => {
let searchResult = comment.filter((item) => {
// console.log(item);
// console.log(item[searchType].includes(inputSearch)); // includes -> 포함 여부를 T/F로 반환
if (!item[searchType].includes(inputSearch)) {
return null;
}
return item;
});
setResult(searchResult); // 검색어 결과 설정
setInputSearch("");
};
// search type에 따라서 어떤 검색을 할지 결정
const selectSearchType = (e) => {
setSearchType(e.target.value);
};
return (
<>
<form>
<label htmlFor="writer">작성자: </label>
<input
type="text"
name="writer"
id="writer"
value={inputWriter}
onChange={(e) => {
setWriter(e.target.value);
}}
/>
{" "}
<label htmlFor="title">제목: </label>
<input
type="text"
name="title"
id="title"
value={inputTitle}
onChange={(e) => {
setTitle(e.target.value);
}}
/>
{" "}
<button type="button" onClick={addContent}>
작성
</button>
</form>
{/* 검색 폼 */}
<form>
<select name="type" onChange={selectSearchType}>
<option value={"writer"}>작성자</option>
<option value={"title"}>제목</option>
</select>{" "}
<input
type="text"
onChange={(e) => {
setInputSearch(e.target.value);
}}
placeholder="검색어를 입력 해 주세요."
value={inputSearch}
name="search"
/>{" "}
<button type="button" onClick={searchComment}>
검색
</button>
</form>
<table border={1} style={{ margin: "30px auto", width: "500px" }}>
<thead>
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
</tr>
</thead>
<tbody>
{comment.map((value, idx) => {
return (
<tr key={idx + 1}>
<td>{idx + 1}</td>
<td>{value.title}</td>
<td>{value.writer}</td>
</tr>
);
})}
</tbody>
</table>
<h4>검색 결과</h4>
{result.length == 0 ? (
<h3>검색 결과가 없어요🥲</h3>
) : (
<table border={1} style={{ width: "500px", margin: "0 auto" }}>
<thead>
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
</tr>
</thead>
<tbody>
{result.map((el, i) => {
return (
<tr key={i + 1}>
<td>{i + 1}</td>
<td>{el.title}</td>
<td>{el.writer}</td>
</tr>
);
})}
</tbody>
</table>
)}
</>
);
}
'🌱SeSAC x CodingOn 웹 취업 부트캠프' 카테고리의 다른 글
[새싹/코딩온] 풀스택 웹 개발자 취업 부트캠프 11주차 (1): React (0) | 2025.01.07 |
---|---|
[새싹/코딩온] 풀스택 웹 개발자 취업 부트캠프 10주차: 프로젝트 회고 (3) (0) | 2025.01.07 |
[새싹/코딩온] 풀스택 웹 개발자 취업 부트캠프 9주차: 프로젝트 회고 (2) (0) | 2025.01.07 |
[새싹/코딩온] 풀스택 웹 개발자 취업 부트캠프 8주차: 프로젝트 회고 (1) (0) | 2025.01.06 |
[새싹/코딩온] 풀스택 웹 개발자 취업 부트캠프 7주차 (2): JWT, 비밀번호 암호화 (1) | 2025.01.05 |