-
벨로퍼트 블로그 React 1~10 정리프로그래밍/React 2021. 7. 28. 15:56
1. 리액트는 어쩌다 만들어졌나
JS 는 DOM 을 선택하고 (브라우저의 DOM Selector API 를 이용해서), 선택한 DOM 에 특정 이벤트가 발생하면 어떤 로직을 실행한다.
"## 이벤트가 발생하면, id가 ** 인 DOM 을 선택하고, 거기서 && 속성을 변경한다"
처리할 이벤트, 관리할 DOM 및 상태값이 다양해지면 ... 매우 복잡해진다
그래서 프레임워크가 만들어졌는데, JS 의 특정값이 바뀌면, 특정 DOM 의 속성이 바뀌도록 연결을 해줘서, 업데이트 작업을 간소화해 주는 방식으로 웹개발의 어려움을 해결해주었다. 리액트의 경우는, 상태가 바뀔 때, 상태에 따라 DOM 을 어떻게 업데이트할 지 정하는 게 아니라 다 날리면 어떨까? 에서 시작되었다.
Virtual DOM 이 등작하였다. 메모리에 가상으로 존재하는 DOM 이므로, 실제 브라우저의 DOM 보다 훨씬 빠르다. 어떤 상태가 업데이트 되면, Virtual DOM 을 통해 렌더링한다. 리액트의 어떤 알고리즘을 통해 비교를 해서 차이가 있는 곳만 변화시켜준다.
4. JSX 기본규칙
태그는 닫혀있어야 한다. 태그 사이에 내용이 없어도 Self Closing 해줘야 한다. < />
2개 이상의 태그는 무조건 1개의 태그로 감싸있어야 한다 <> </> 빈 태그로 감싸줘도 된다.
JS 변수를 보여줘야 할 때는 {} 로 감싼다
style 을 작성할 때는 CamelCase 를 따른다. class 는 className= 으로 작성한다
5. props 를 통해 컴포넌트에 값 전달하기
값을 받아올 때는 props 로 해서 받아올 수도 있고, 그냥 직접 그 속성으로 쓴 값을 쓸 수도 있다.
function App() { return ( <Hello name="react" color="red"/> ); }
props 를 인자에 쓰고, props.color, props.name 으로 접근하거나, color, name 을 직접 인자에 쓰고, color, name 으로 접근한다.
function Hello(props) { return <div style={{ color: props.color }}>안녕하세요 {props.name}</div> }
function Hello({ color, name }) { return <div style={{ color }}>안녕하세요 {name}</div> }
data 속성을 넘겼으면, 인자에 data 를 쓰고 직접 받는다. data 로 들어온 객체에는 data.id 이런 식으로 접근하면 된다.
return <CommentBox data={item} key={idx} />;
const CommentBox = ({ data }) => { return ( <div className={styles.item}> <div> <h4>Comment Id</h4> {data.id} </div>
defaultProps 로 기본값을 설정할 수 있다.
6. 조건부 렌더링
단순히 특정 조건이 true 일 때 보여주고, 그렇지 않을 떄 숨기는 거라면 && 연산자를 사용하는 것이 더 간편하다
props 값 설정을 생략하면 ={true} 이다
7. useState 를 통해 컴포넌트에서 바뀌는 값 관리하기
onClick 과 같은 이벤트 속성에 함수 이름을 작성하고, 함수 안에 Setter 함수를 넣어주면 된다. Setter 함수에서 직접 인자로 state 변수에 값을 바꿀 수도 있지만, 이전 값에 접근해서 어떻게 바꿔줄 지 함수를 등록하는 식으로 할 수도 있다.
function Counter() { const [number, setNumber] = useState(0); const onIncrease = () => { setNumber(number + 1); } return ( <div> <h1>{number}</h1> <button onClick={onIncrease}>+1</button>
const onIncrease = () => { setNumber(prevNumber => prevNumber + 1); }
8. input 상태 관리하기
input 의 onChange 이벤트를 사용한다. 이벤트에 등록하는 함수에는 이벤트 객체 e를 파라미터로 받아와서 사용할 수 있다. e.target 은 이벤트가 발생한 DOM 인 input DOM 을 가리키고, 이 DOM 의 value 값, 즉 e.target.value 에 현재 input 에 입력돼 있는 값이 있다.
import React, { useState } from 'react'; function InputSample() { const [text, setText] = useState(''); const onChange = (e) => { setText(e.target.value); }; const onReset = () => { setText(''); }; return ( <div> <input onChange={onChange} value={text} /> <button onClick={onReset}>초기화</button> <div> <b>값: {text}</b> </div> </div> ); } export default InputSample;
input 의 상태를 관리할 때는 input 태그의 value 값도 설정해주는 것이 중요하다, 그렇게 해야 상태가 바뀔 때 input 내용도 바뀐다.
9. 여러 개의 input 상태 관리하기
input 이 비어있을 때 설명해주는 placeholder 값도 넣어주겠다. input 이 여러 개 일때는, useState 를 여러 번 사용하지 말고 다음과 같이 이용한다. input 에 name 을 설정하고, 이벤트가 발생했을 때 이 값을 참조한다. 그리고 useState 안에 객체 형태로 상태를 관리한다.
import React, { useState } from 'react'; function InputSample() { const [inputs, setInputs] = useState({ name: '', nickname: '' }); const { name, nickname } = inputs; // 비구조화 할당을 통해 각 변수에 해당 state 값을 담음. ES6 const onChange = (e) => { const { value, name } = e.target; // e.target 에서 name, value 값을 추출. 비구조화 할당문법 setInputs({ ...inputs, // 기존 input 객체를 복사해서 담고 [name] : value, }); }; const onReset = () => { setInputs({ name: '', nickname: '', }); }; return ( <div> <input name="name" placeholder="이름" onChange={onChange} value={name} /> <input name="nickname" placeholder="닉네임" onChange={onChange} value={nickname} /> <button onClick={onReset}>초기화</button> <div> <b>값: {text}</b> {name} ({nickname}) </div> </div> ); } export default InputSample;
리액트에서 상태를 수정할 때는 직접 수정하는 게 아니라, useState 를 사용해 상태를 변경해줘야 한다. 또 객체를 수정해야 할 때도 역시, 새로운 객체를 만들어서, 새로운 객체에 변화를 주고, 이를 state 객체를 상태로 사용해야 한다. 이를 "불변성을 지킨다"고 하고, 이에 따라 필요한 리렌더링이 진행된다. 불변성을 지켜야 컴포넌트 업데이트 성능을 최적화 할 수 있다.
07 spread 와 rest
... 이거를 사용한 문법은 spread 문법이다. ES6 부터 도입됐으며, 객체/배열의 내용을 모두 "펼쳐서" 기존 객체/배열을 복사해준다. 객체에서 새로운 객체를 만들면서, 기존의 내용은 살리고, 새로운 속성/값을 추가한다.
const slime = { name: '슬라임' }; const cuteSlime = { ...slime, attribute: 'cute' }; const purpleCuteSlime = { ...cuteSlime, color: 'purple' }; console.log(slime); // { name: '슬라임' } console.log(cuteSlime); // { name: '슬라임', attribute: 'cute' } console.log(purpleCuteSlime); // { name: '슬라임', attribute: 'cute', color: 'purple' }
배열에도 똑같이 적용되고, spread 연산자 (...) 를 여러 번 사용할 수도 있다.
const animals = ['개', '고양이', '참새']; const anotherAnimals = [ ...animals, '비둘기']; console.log(animals); // ['개', '고양이', '참새'] console.log(anotherAnimals); // ['개', '고양이', '참새', '비둘기'] const numbers = [1, 2, 3, 4, 5]; const spreadNumbers = [...numbers, 1000, ...numbers]; console.log(spreadNumbers); // [1, 2, 3, 4, 5, 1000, 1, 2, 3, 4, 5]
rest 는 spread 의 거꾸로라고 생각해도 된다. 객체에서 해당 속성의 값을 변수에 각각 할당해준다.
const purpleCuteSlime = { name: '슬라임', attribute: 'cute', color: 'purple' }; const { color, ...cuteSlime } = purpleCuteSlime; console.log(color); // purple console.log(cuteSlime); // { name: '슬라임', attribute: 'cute' } const { attribute, ...slime } = cuteSlime; console.log(attribute); // cute console.log(slime); // { name: '슬라임' }
객체, 배열에서 사용할 때는 비구조화 할당 문법과 함께 사용된다. 여기 예시까지 보고 나머지는 다음에
10. useRef 로 특정 DOM 선택하기
JS 에서 getElementById, querySelector 같은 DOM Selector 함수를 통해 요소를 선택하듯이, React 에서 ref 를 사용해 요소를 선택한다. 함수형 컴포넌트에서 ref 를 사용할 때는 useRef 라는 Hook 함수를 사용하여, Ref 객체를 만든다.
import React, { useState, useRef } from 'react'; function InputSample() { const nameInput = useRef(); const onReset = () => { setInputs({ name: '', nickname: '' }); nameInput.current.focus(); }; return ( <div> <input name="name" placeholder="이름" onChange={onChange} value={name} ref={nameInput} />
이 객체를 선택하고자 하는 DOM에 ref 값으로 설정해준다. (ref={ref변수명}) ref 변수명을 JS 의 selector 처럼 계속 사용해줄 수 있고, 이 Ref 객체의 .current 값이 우리가 원하는 DOM 을 가리킨다.
위 예제는 위 예제에 ref 를 추가한 것이고, input 에 포커스 하는 focus() DOM API 를 호출하였다.
'프로그래밍 > React' 카테고리의 다른 글
react pagination (0) 2021.09.05 Redux thunk, Ducks pattern, Router 연결, Redux saga 등 (0) 2021.08.13 Redux 와 React 연결, 비동기 with Redux (0) 2021.08.12 Redux 강의 정리 (0) 2021.08.09 npm, yarn (0) 2021.08.08