juni
State , Props , useRef , Hooks 본문
State와Props 활용
import "./App.css";
import { useState } from "react";
import Bulb from "./components/Bulb";
import Counter from "./components/Counter";
//함수 컴포넌트 리랜더링 -> App함수 재호출하고 바뀐 값을 재랜더링
//자신이 관리하는 state 값 변경시 , 자신이 제공 받는 props값이 변경시
//부모 component 리랜더링시 자신도 리랜더링 -> 위 3가지 경우 리랜더링
// 컴포넌트를 나누어 불필요한 리랜더링 방지
function App() {
return (
<>
<Bulb />
<Counter />
</>
);
}
export default App;
import { useState } from "react";
const Bulb = () => {
//[state값 , 변경시킬 함수]
const [light, setLight] = useState("off");
// let light="off"
return (
<div>
{light === "on" ? (
<h1 style={{ backgroundColor: "orange" }}>on</h1>
) : (
<h1 style={{ backgroundColor: "gray" }}>off</h1>
)}
<div>
<button
onClick={() => {
setLight(light === "on" ? "off" : "on");
// 스테이트의 상태가 변한게 아니므로 리랜더링X
// light = light === "on" ? "off" : "on";
}}
>
{light === "on" ? "끄기" : "켜기"}
</button>
</div>
</div>
);
};
export default Bulb;
import { useState } from "react";
const Counter = () => {
const [count, setCount] = useState(0);
return (
<div>
<h1>{count}</h1>
<button
onClick={() => {
setCount(count + 1);
}}
>
+
</button>{" "}
</div>
);
};
export default Counter;
단순 활용
import { useState } from "react";
//간단한 회원가입 폼
//이름 , 생년월일 , 국적 , 자기소개
//State를 이용한 저장법
const Register = () => {
const [name, setName] = useState("이름");
const [birth, setBirth] = useState("");
const [country, setCountry] = useState("");
const [bio, setBio] = useState("");
//이벤트 핸들러
const onChangeName = (e) => {
setName(e.target.value);
};
const onChangeBirth = (e) => {
setBirth(e.target.value);
};
const onChangeCountry = (e) => {
setCountry(e.target.value);
};
const onchangeBio = (e) => {
setBio(e.target.value);
};
return (
<div>
<div>
{/* input의 값이 변경 되었을 때 : onChange
placeholder : 인풋 내부에 흐린 글씨로 표시
value는 onchange내 함수 호출시 state의 name에 값 저장*/}
<input value={name} onChange={onChangeName} placeholder={"이름"} />
</div>
<div>
<input value={birth} onChange={onChangeBirth} type="date" />
</div>
<div>
<select value={country} onChange={onChangeCountry}>
<option value=""></option>
<option value="kr">한국</option>
<option value="us">미국</option>
<option value="uk">영국</option>
</select>
{country}
</div>
<div>
<textarea value={bio} onChange={onchangeBio} />
</div>
</div>
);
};
export default Register;
State및 EventHandler효율적으로 통합
import { useState } from "react";
//간단한 회원가입 폼
//이름 , 생년월일 , 국적 , 자기소개
//State를 이용한 저장법
const Register = () => {
// const [name, setName] = useState("이름");
// const [birth, setBirth] = useState("");
// const [country, setCountry] = useState("");
// const [bio, setBio] = useState("");
//이벤트 핸들러
// const onChangeName = (e) => {
// setName(e.target.value);
// };
// const onChangeName = (e) => {
// setInput({
// //...input 스프레드 연산자로 다른 프로퍼티(속성) 값들을 그대로 유지 가능
// //누락시 다른 속성들이 사라져버림
// ...input,
// name: e.target.value,
// });
// };
// console.log(input);
//State를 객체로 만들어 통합하여 관리
const [input, setInput] = useState({
name: "",
birth: "",
country: "",
bio: "",
});
//4개의 이벤트 핸들러 압축 (통합 핸들러)
//onChange함수 실행 -> setInput 상태변화 함수 호출 -> 인수로 객체를 만들어저장
//스프레드 연산자로 input값 나열 -> 프로퍼티 키 명시 위치에 ([여기])
//여기에 변수의 이름을 기재시 값이 프로퍼티 키로 설정가능
const onChange = (e) => {
//e.target.name은 아래 birth bio등 값이 들어감
console.log(e.target.name, e.target.value);
setInput({
...input,
[e.target.name]: e.target.value,
});
};
return (
<div>
<div>
{/* input의 값이 변경 되었을 때 : onChange
placeholder : 인풋 내부에 흐린 글씨로 표시
value는 onChange내 함수 호출시 state의 name에 값 저장
name은 핸들러 타겟의 이름 설정 */}
<input
name="name"
value={input.name}
onChange={onChange}
placeholder={"이름"}
/>
</div>
<div>
<input
name="birth"
value={input.birth}
onChange={onChange}
type="date"
/>
</div>
<div>
<select name="country" value={input.country} onChange={onChange}>
<option value=""></option>
<option value="kr">한국</option>
<option value="us">미국</option>
<option value="uk">영국</option>
</select>
</div>
<div>
<textarea name="bio" value={input.bio} onChange={onChange} />
</div>
</div>
);
};
export default Register;
useRef 추가 적용
import { useState, useRef } from "react";
//간단한 회원가입 폼
//이름 , 생년월일 , 국적 , 자기소개
//State를 이용한 저장법
const Register = () => {
// const [name, setName] = useState("이름");
// const [birth, setBirth] = useState("");
// const [country, setCountry] = useState("");
// const [bio, setBio] = useState("");
//이벤트 핸들러
// const onChangeName = (e) => {
// setName(e.target.value);
// };
// const onChangeName = (e) => {
// setInput({
// //...input 스프레드 연산자로 다른 프로퍼티(속성) 값들을 그대로 유지 가능
// //누락시 다른 속성들이 사라져버림
// ...input,
// name: e.target.value,
// });
// };
// console.log(input);
//State를 객체로 만들어 통합하여 관리
//useState 리랜더링 되더라도 리셋되지않고 유지
const [input, setInput] = useState({
name: "",
birth: "",
country: "",
bio: "",
});
//reference는 state와 비슷하지만 리랜더링X
const countRef = useRef(0);
const inputRef = useRef();
//Register컴포넌트가 계속 리랜더링 되면서 전체를 재호출하므로 count=1이 고정
//전역으로 설정하면 영향을 받진 않지만 App.jsx에서 Register컴포넌트를
//여러번 호출시 컴포넌트간 전역변수를 공유하므로 바람직하지않음
//필요하다면 useRef를 활용하는게 좋음
let count = 0;
//4개의 이벤트 핸들러 압축 (통합 핸들러)
//onChange함수 실행 -> setInput 상태변화 함수 호출 -> 인수로 객체를 만들어저장
//스프레드 연산자로 input값 나열 -> 프로퍼티 키 명시 위치에 ([여기])
//여기에 변수의 이름을 기재시 값이 프로퍼티 키로 설정가능
const onChange = (e) => {
//e.target.name은 아래 birth bio등 값이 들어감
// console.log(e.target.name, e.target.value);
// countRef.current++;
count++;
console.log(count);
setInput({
...input,
[e.target.name]: e.target.value,
});
};
const onSubmit = () => {
if (input.name === "") {
//이름을 입력하는 DOM 요소 포커스(선택된 상태)
//console.log(inputRef.current);
inputRef.current.focus();
}
};
return (
<div>
<div>
{/* input의 값이 변경 되었을 때 : onChange
placeholder : 인풋 내부에 흐린 글씨로 표시
value는 onChange내 함수 호출시 state의 name에 값 저장
name은 핸들러 타겟의 이름 설정 */}
<input
ref={inputRef}
name="name"
value={input.name}
onChange={onChange}
placeholder={"이름"}
/>
</div>
<div>
<input
name="birth"
value={input.birth}
onChange={onChange}
type="date"
/>
</div>
<div>
<select name="country" value={input.country} onChange={onChange}>
<option value=""></option>
<option value="kr">한국</option>
<option value="us">미국</option>
<option value="uk">영국</option>
</select>
</div>
<div>
<textarea name="bio" value={input.bio} onChange={onChange} />
</div>
<button onClick={onSubmit}>제출</button>
</div>
);
};
export default Register;
Hook 추가
import useInput from "../hooks/useInput";
// 훅 : classComponent의 기능을 functionComponent에서도 사용가능하도록 끌어오는 것
// 종류가 20가지정도로 상당히 많음 -> useState , useRef등도 여기 포함됨
import { useState } from "react";
// 훅은 반드시 함수 컴포넌트or커스텀 훅 내부에서만 호출 가능
// 조건부로 호출 될 수는 없다 -> 조건문이나 반복문 안에서 호출 할 수 없다.
// ->컴포넌트를 호출하여 랜더링시 서로 다른 훅의 순서가 꼬일 수 있어 막아뒀다.
// 개발자가 임의로 만드는 customHook을 직접 만들 수 있다
const HookExam = () => {
const [input, onChange] = useInput();
const [input2, onChange2] = useInput();
return (
<div>
<input value={input} onChange={onChange} />
<input value={input2} onChange={onChange2} />
</div>
);
};
export default HookExam;
import { useState } from "react";
//훅은 컴포넌트 와 별개로 훅 폴더에 따로 저장해주는게 좋음
//커스텀 훅 : 함수명앞에use를 붙여주면 훅으로 인식함
function useInput() {
const [input, setInput] = useState("");
const onChange = (e) => {
setInput(e.target.value);
};
return [input, onChange];
}
export default useInput;
'CS' 카테고리의 다른 글
JS 문법 복습 및 React 학습 (0) | 2024.05.13 |
---|---|
JS 문법 복습 (0) | 2024.05.12 |
JS 문법 복습 (0) | 2024.05.10 |
콜백함수 (0) | 2024.04.30 |
호이스팅, this (0) | 2024.04.29 |