3-2 : React 기초 (엘리스 AI 트랙)
[엘리스 AI 트랙] 3주차 - 2
- 온라인 강의, 실습 내용 정리본
- 10/8 금요일
React 기초
1. props와 State
01. Props (Properties)
1) Props란?
- 컴포넌트에 원하는 값을 넘겨줄 때 사용
- 변수, 함수, 객체, 배열 등 제한 없이 JS 요소를 넘겨줄 수 있다.
- 주로 컴포넌트의 재사용을 위하여 사용
// 컴포넌트 생성
const Greeting = (props) => {
return <h1>Hi, My name is {props.name}</h1>;
}
// 컴포넌트 사용
const App =() => {
return <div>
<Greeting name="IceBear" />
<Greeting name="Panda" />
<Greeting name="Greezly" />
</div>;
}
2) Props는 읽기 전용
: props 값 임의 변경 사용하면 X. 변경 원할 시 새로운 변수 사용하기.
// 잘못된 코드!!!!!!!!!!!! 오류는 아니지만 잘못된 사용임!!
const Greeting = (props) => {
props.name = props.name + "곰";
return <h1>Hi, My name is {props.name}</h1>;
}
// 올바른 사용법
const Greeting = (props) => {
const bear = props.name + "곰";
return <h1>Hi, My name is {bear}</h1>;
}
3) DOM Element의 Attributes
- 기본적인 DOM Element(div, span 등)들의 Attribute
:camel case
로 작성. (예: tabIndex, className 등) ‘data-’
또는‘aria-’
로 시작하는 Attribute는 예외!- HTML의 Attribute와 다른 이름을 가지는 Attribute 주의하기. (class →
className
, for →htmlFor
등) - HTML의 Attribute와 다른 동작 방식을 가진 Attribute 주의하기. (checked(
defaultChecked
), value(defaultValue
),style
등) - React에서만 쓰이는 새로운 Attribute 주의하기. (
key
등)
4) HTML과 다른 방식의 React Attribute (checked, value)
- HTML에서 checked 또는 value는 해당 값이
초기값
vs React 내에서는현재 값
을 의미 - 즉, checked 값이 false로 설정돼있으면 체크박스 클릭해도 값의 변화 없다.
- 초기값의 의미로 checked 또는 value를 사용하려면
defaultChecked, defaultValue
속성으로 설정!
(<input type="checkbox" checked={false} />)
5) React에서만 쓰이는 새로운 Attribute(key)
Key
는 React가 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 돕는다.- Key는 엘리먼트에 안정적인 고유성을 부여하기 위해 배열 내부의
Element
에 지정해야 함 - Key는 배열 내부 형제 사이에서 고유해야 하고 전체에서 고유할 필요 X. → 다른 배열을 만들 때는 key 같아도 O.
const Bears = () => {
const bears = [
{key: '3', value: 'iceBear'},
{key: '1', value: 'greezly'},
{key: '2', value: 'panda'}
]
return (
<div>
{bears.map((item) => (
<li key={item.key}>{item.value}</li>
))}
</div>
);
}
02. State
1) State란?
: State는 컴포넌트 내부, 지속적으로 변경이 일어나는 값을 관리하기 위해 사용.
const App = () => {
const [value, setValue] = useState(초기값); // value: state명, setValue: set+State명
return ...
}
- useState import 하기
import { useState } from "react";
- State 값 변경시 꼭 setState 함수로! state 값을 임의로 변경하지 말자.
const [value, setValue] = useState(""); ... setValue("안녕하세요");
- State는 Component 내에서 유동적인 값을 저장. 개발자 의도나 사용자 입력에 의해 변할 수 있다. State 값 변경되고 재렌더링이 필요하면 React가 자동으로 변경된 부분 렌더링. (이러기 위해서는 setState 함수 사용 필수. 임의 변경시 리액트가 알아차리지 못함!)
import {useState} from 'react'; function DoorBell(){ const [cnt, setCnt] = useState(0); return ( <div> <button onClick={() => setCnt(cnt + 1)}>딩동</button> <p>초인종을 {count}번 눌렀다!</p> </div> ); }
2) State를 변경하는 두 가지 방법
- setState 내에 변경할 값 넣기
const [count, setCount] = useState(0); setCount(count+1);
- setState에 함수를 넣기 : 함수가 반환(return)하는 값으로 State가 변경
→ 현재 값을 기반으로 State를 변경할 땐 함수를 넣는 방법을 권장const [count, setCount] = useState(0); setCount((current) => { return current + 1; });
3) 배열이나 객체를 갖는 State 만들 때 주의사항
: 예시의 경우 React가 State의 변경을 감지하지 못함! 내용물만 바뀌고 bear 객체 자체가 변경되지 않았기 때문! 리액트는 객체와 배열은 그 자체가 변경될 경우에만 다시 렌더링
함!!!!!!!!!
(예를 들어 마치 슈뢰딩거의 고양이.. 고양이가 박스 안에서 살아있는 상태에서 죽은 상태로 바뀌어도 박스 밖에선 모른다. 리액트는 우리처럼 모른다.)
// 잘못된 사용
const [bear, setBear] =
useState({name: "iceBear", age: 5})
setBear((current) => {
current.age = 6;
return current;
})
// 올바른 사용
const [bear, setBear] =
useState({name: "iceBear", age: 5})
setBear((current) => {
const newBear = {...current};
newBear.age = 6;
return newUser;
})
2. 이벤트 처리
01. 이벤트 소개
1) 이벤트란?
: 이벤트(event)란 웹 브라우저가 알려주는 HTML 요소에 대한 사건의 발생. 유저의 행동, 개발자 의도한 코드에 의해 발생할 수도 있다. Element가 로딩되었을 때, Element를 클릭, 마우스 오버, 더블 클릭, 키보드 입력 등 다양한 이벤트가 존재. 이벤트 핸들러 함수는 이벤트 생겼을 때 처리하는 방법이다.
2) 이벤트 처리(핸들링) 방법
: React에서 이벤트를 처리하는 방법은 크게 두 가지! 별도의 핸들링 함수를 선언하고 Element에 넘겨주는 방법과 이벤트를 할당하는 부분에서 익명 함수를 작성하는 방법으로 나뉜다.
- 핸들링 함수 선언
const App = () => { const handleClick = () => { console.log("눌렀다!"); } return ( <div> <button onClick={handleClick}>눌러보자</button> </div> ); }
- 익명 함수로 처리
const App = () => { return ( <div> <button onClick={() => {console.log('눌렀다!')}}>눌러보자</button> </div> ) }
3) 이벤트 객체
- DOM Element의 경우 핸들링 함수에
event
object를 매개변수로 전달. event
object를 이용하여 이벤트 발생 원인, 이벤트가 일어난 Element에 대한 정보 접근 가능.- 이벤트 형태와 DOM 종류(button, form, input 등)에 따라 전달되는 이벤트 object의 내용 다름.
- 참고: https://developer.mozilla.org/ko/docs/Web/API/Event
const App = () => {
const handleChange = (event) => {
alert(event.target.value + '라고 입력했어요!'); // event.target은 이벤트가 일어난 엘리먼트를 뜻함.
}
return (
<div>
<input onChange={handleChange} />
</div>
);
}
4) 많이 쓰이는 DOM 이벤트
onClick
: Element를 클릭했을 때
onChange
: Element의 내용이 변경되었을 때(input의 텍스트를 변경, 파일 선택 등)
onKeyDown, onKeyUp, onKeyPress
: 키보드 입력이 일어났을 때
onDoubleClick
: Element를 더블 클릭했을 때
onFocus
: Element에 Focus되었을 때
onBlur
: Element가 Focus를 잃었을 때
onSubmit
: Form Element에서 Submit 했을 때
02. 컴포넌트 내 이벤트 처리
1) DOM Input 값을 State에 저장하기
: event object의 target은 이벤트의 원인이 되는 Element를 가리킨다. 현재 event의 target은 input element이므로 입력된 value를 가져와 setState를 하는 예시.
const App = () => {
const [inputValue, setInputValue] =
useState("");
const handleChange = (event) => {
setInputValue(event.target.value);
}
return (
<div>
<input onChange={handleChange} defaultValue={inputValue} />
<br />
입력한 값: {inputValue}
</div>
);
}
2) 여러 Input 동시에 처리하기
: 한 개의 이벤트 핸들링 함수를 재사용해 여러 input element에서 값을 입력받는 방법
-
object 값 변경 시 보통
object.key = "value"
와 같이 작성하는데 -
그 대신,
object["key"] = "value"
처럼 작성할 수 있고"key"
자리에 변수를 대입하여 다이나믹하게 값 변경 가능. -
Dynamic key 예시
const obj = {
a: "example1",
b: "example2",
c: "example3"
}
const key = "b";
obj[key] = "수정"
console.log(obj);// { a: "example11", b: "수정", c: "example3" }
-
이런 Object 특성을 이용 → 한 개의 이벤트 핸들링 함수로 여러 element의 이벤트를 처리 가능!
: 여러 State 선언 대신 object를 활용하여 여러 개의 input을 state로 관리하는 방법이 있다. target으로부터 name을 받아와 해당 name의 key에 해당하는 value를 변경하여 state에 반영하기!
const App = () => {
const [bearInfo, setBearInfo] = useState({bearName: "아이스베어", home: "동굴"});
const handleChange = (event) => {
const {name, value}
const newBearInfo = {...bearInfo};
newBearInfo[name] = value;
setUser(newBearInfo);
};
return (
<div>
<input name="bearName" onChange={handleChange} value={bearInfo.bearName} />
<br />
<input name="home" onChange={handleChange} value={bearInfo.home} />
<p>
내 친구 {bearInfo.bearName}는 {bearInfo.home}에 살고 있어요.
</p>
</div>
);
}
03. 다른 컴포넌트로 이벤트 전달
1) 컴포넌트간 이벤트 전달하기
: 입력 받은 정보를 부모 컴포넌트에서 활용해야 하는 경우 이벤트를 Props로 전달하여 처리
const MyForm = ({onChange}) => {
return (
<div>
<span>곰 이름: </span>
<input onChange={onChange} />
</div>
);
}
const App = () => {
const [bearname, setBearname] = useState('');
return (
<div>
<h1>{bearname} 곰이에요.</h1>
<MyForm
onChange={(event) => {
setBearname(event.target.value)
}}
/>
</div>
);
}
2) 커스텀 이벤트
const RingDingDong = ({onRingDingDong}) => {
const [count, setCount] = useState(0);
const handleClick = () => {
if(count >= 2) {
onRingDingDong();
}
setCount(count + 1);
}
return <button onClick={handleClick}>
똑똑똑 버튼 세번 누르면 문이 열립니다.({count})
</button>
}
const App = () => {
return (
<div>
<RingDingDong
onSOS={() => {
alert("문 열어주기!");
}}
/>
</div>
);
};
3) 이벤트 명명법
- 직접 이벤트 제작 시 이름 자유 설정 가능. 보통은 관습적으로
“on” + 동사
or“on” + 명사 + 동사
형태로 작성. (예: onClick, onInputChange) - 핸들링 함수의 경우,
“handle” + 동사
or“handle” + 명사 + 동사
의 형태로 작성. “handle” 대신 이벤트명과 동일한 “on”을 앞에 붙여도 O. (예. handleClick)
3. Hooks
01. Hooks 개요
1) Hook이란?
: 함수 컴포넌트에서 데이터를 관리(State)하고 데이터가 변경될 때 상호작용(Effect)을 하기 위해 사용
2) 유의사항
- Hook은 React 함수(컴포넌트, Hook) 내에서만 사용 가능
- Hook의 이름은 반드시
**use**
로 시작 - 최상위 Level에서만 Hook을 호출할 수 있다. (if문, for문 안 쪽 또는 콜백함수 내에서 호출 불가)
const App = () => {
const [name, setName] = useState('')
return (
<div>
<h1>{name}님 접속하셨네요!</h1>
</div>
);
}
02. State Hook과 Effect Hook
1) State Hook
- useState는 컴포넌트 내 동적인 데이터를 관리할 수 있는 hook.
- 최초에 useState가 호출될 때 초기값으로 설정되고 이후 재 렌더링이 되면 초기값 무시.
- state는 읽기 전용이므로 직접 수정 불가!! (사실 가능한데 이렇게 하면 재 렌더링이 안 됨.)
- state를 변경하기 위해서는 setState를 이용.
- state가 변경되면 자동으로 컴포넌트가 재 렌더링 됨.
const App = () => {
// 일반적인 useState 사용법
const [state이름, setState이름] = useState(초기값);
}
- state 변경 방법 두 가지 :
setState 함수에 직접 값을 입력
현재 값을 매개변수로 받는 함수를 전달
: 함수에서 return되는 값이 state에 반영 됨.
const App = () => {
const [lyrics, setLyrics] = useState("");
// State를 변경할 값을 직접 입력
setLyrics("안녕하세요. 선생님~")
// 또는 현재 값을 매개변수로 받는 함수 선언
// return 값이 state에 반영됨
setLyrics((current) => {
return current + "안녕? 친구야";
})
}
2) Effect Hook
- Effect Hook을 사용하면 함수 컴포넌트에서 side effect 수행 가능.
- 컴포넌트가 최초로 렌더링될 때 & 지정한 State나 Props가 변경될 때마다 effect 콜백 함수가
호출 됨. Deps
: 변경을 감지할 변수들의 집합(배열)EffectCallback
: Deps에 지정된 변수가 변경될 때 실행할 함수
const App = () => {
useEffect(EffectCallback, Deps?)
}
const App = () => {
const [count, setCount] = useState(0);
useEffect(() => {
console.log('버튼 클릭 : ${count} 번')
}, [count])
return (
<div>
<button onClick={() => setCount(count + 1)}>
클릭!
</button>
</div>
)
}
- useEffect의 이펙트 함수 내에서 다른 함수를 return할 경우
: state가 변경되어 컴포넌트가 다시 렌더링되기 전과 컴포넌트 소멸 시(Destroy) 호출할 함수를 지정.
const App = () => {
useEffect(() => {
// State가 변경될 때, 컴포넌트를 렌더링할 때
const intervalId = setInterval(()=>{
console.log("State가 변경될 때, 컴포넌트를 렌더링할 때 실행!");
}, 3000);
// 컴포넌트를 재 렌더링 하기 전에, 컴포넌트가 없어질 때만 실행될 함수 지정
return () => {
clearInterval(intervalId);
}
}, [])
...
03. 이외의 Hooks
- useMemo
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b])
-
메모이제이션 된
값
반환 -
지정한 State나 Props가 변경될 경우 해당 값을 활용해 계산된 값을 메모이제이션하여 재렌더링 시 불필요한 연산을 줄인다.
-
useMemo의 연산은 렌더링 단계에서 이루어짐 → 시간이 오래 걸리는 로직을 작성하지 않는 것이 권장됨.
const App = () => { const [mammal, setMammal] = useState('bear') const [animalName, setAnimalName] = useState('ice') // 포유류 또는 동물 이름이 바뀔 때마다 메모이제이션 // useMemo 내부 함수에서 리턴된 값이 animalFullName 변수에 들어간다. const animalFullName = useMemo(() => { return ′${animalName} ${mammal}′ }, [animalName, mammal]) }
-
-
useCallback
const memoizedCallback = useCallback( () => { doSomething(a, b); }, [a, b] );
-
메모이제이션 된
콜백 함수
반환 -
컴포넌트가 재렌더링될 때 불필요하게 함수가 다시 생성되는 것 방지
-
useMemo(() => fn, deps) 와 useCallback(fn, deps) 는 같다. (useMemo에서 함수를 리턴해주는 것과 useCallback은 일치) → 단지 개발자의 편의를 위해 분리했다고 생각하자
const App = () => { const [mammal, setMammal] = useState('bear') const [animalName, setAnimalName] = useState('ice') // 포유류 또는 동물 이름이 바뀔 때마다 // 풀네임을 return하는 함수를 메모이제이션 const getAnimalFullName = useCallback(() => { return ′${animalName} ${mammal}′ }, [animalName, mammal]) return <>{getAnimalFullName()}</> }
-
- useRef
const refContainer = useRef(initialValue);
-
컴포넌트 생애 주기 내에서 유지할 ref 객체를 반환
-
ref 객체는
.current
라는 프로퍼티를 가지며 이 값을 자유롭게 변경할 수 있다. -
일반적으로 React에서 DOM Element에 접근 할 때 사용(DOM Element의 ref 속성
이용) -
useRef에 의해 반환된 ref 객체가 변경되어도 컴포넌트가 재렌더링되지 않는다.
const App = () => { const inputRef = useRef(null) const onButtonClick = () => { inputRef.current.focus() } return ( <div> <input ref={inputRef} type="text" /> <button onClick={onButtonClick}> input으로 포커스 이동하기 </button> </div> ) }
-
04. 커스텀 Hook
1) Custom Hook
: UI 요소의 재사용성을 높이기 위해 컴포넌트를 만드는 것처럼, 로직의 재사용성을 높이기 위해 Custom Hook을 제작. ⇒ 커스텀 훅은 그냥 훅을 사용하는 함수임!
function useMyHook(args) {
const [status, setStatus] = useState(undefined);
// ...
return status;
}
- 한 로직이 여러 번 사용될 경우 함수를 분리하는 것처럼 Hook을 만드는 것
- Hook의 이름은 ‘use’로 시작해야 한다.
- 한 Hook 내의 state는 공유되지 않는다.
Author And Source
이 문제에 관하여(3-2 : React 기초 (엘리스 AI 트랙)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@sue/3-2-React-기초-엘리스-AI-트랙저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)