TIL_220603_React

설탕유령·2022년 6월 3일
0

CSS Flex
CSS Grid

var, let, const

var은 함수 단위로 정의됨
let은 Block 단위로 정의됨

function test(){
  var a = 0;
  let b = 0;
  
  if (a === 0){
    var a = 1;
    let b = 1;
  }
  console.log(a, b);
  // a = 1, b = 0
  // a는 함수 단위로 동작하기 때문에 if block 안에서 정의한 a = 1이 if 바깥에서도 유효함
  // b는 블록 단위기 때문에 if를 벗어나는 순간 b = 1의 효력이 사라짐
}

[Component]
리액트는 레고, 컴포넌트는 블록

<!DOCTYPE html>
<html lang="en">
  <head>
  </head>
  <body>
    <header>
    ...
    </header>
    <div class="container">
      <div id="image-banner">
      ...
      </div>
      <div id="contents-1">
      ...
      </div>
    </div>
    <footer>
    ...
    </footer>
  </body>
</html>

HTML 구조가 있을때 Component로 구성시 다음과 같음

  1. <header/>
  2. <container/>
    a. <imagebanner/>
    b. <contents1/>
  3. <footer/>

자식 컴포넌트가 부모 컴포넌트로 전달 받은 데이터를 props라고 함
Props로 받은 데이터는 수정 할 수 없음

자식 컴포넌트는 부모 컴포넌트에 속해있음

  • 자식 컴포넌트는 return에 들어있는 리액트 요소를 부모 컴포넌트에 가져다 줌
  • 즉 자식 컴포넌트가 css를 안가져와도, 부모에 적용된 css가 자식 컴포넌트 return 값에 적용 됨
yarn add styled-components

컴포넌트 스타일링 기법 중 하나

  • CSS-in-JS 라이브러리 중 하나
  • 컴포넌트에 스타일을 직접 익히는 방식
  • class 이름 짓기에서 해방됨
  • 컴포넌트에 스타일을 적기 때문에 직관적이고 간단함

[리액트에서 DOM 요소 사용]
방법 1: React.createRef()

  • this.text = React.createRef();
  • <input type="text" ref={this.text} />

방법 2: React.useRef()

  • const my_wrap = React.useRef(null);
  • <div ref={my_wrap}>

[State 관리]
단방향 데이터 흐름

  • 데이터는 위에서 아래로, 부모에서 자식으로 넘겨줘야함
  • 부모 컴포넌트 state가 업데이트 되면 자식 컴포넌트도 리렌더링이 일어남
  • 만약 자식 컴포넌트 state가 바뀐 걸 부모가 props로 받는 경우 자식이 업데이트 될 때 부모가 업데이트 되고, 부모가 업데이트 됬으니 자식이 또 리렌더링 됨

State 관리 방법 1: setState()
this.state = { count: 3, };
this.setState({ count: this.state.count - 1 });

State 관리 방법 2: useState()
const [count, setCount] = React.useState(3);
count에는 state 값이, setCount는 count라는 state 값을 수정하는 함수가 됨
setCount(count + 1);

[Event]
addEventListener()를 통해 특정 요소에 이벤트를 등록 가능
this.특정요소.current.addEventListener("mouseover", this.이벤트명);

useEffect()는 리액트 훅

  • 라이프 사이클 함수 중 componentDidMount와 componentDidUpdate, componentWillUnmount를 합쳐둔 것
// 첫번째 인자는 렌더링 시 실행할 함수
// 두번째 인자[]! 디펜던시 어레이가 변하면 첫번째 인자 함수를 호출함
React.useEffect(() => {
  // rendering 때 실행될 구문
  // componentDidMount, componentDidUpdate일 때 동작하는 부분
  text.current.addEventListener("mouseover", hoverEvent);
  return () => {
    // clean up 부분
    // componentWillUnmount 때 동작하는 부분
    // 이벤트는 컴포넌트가 사라지면 지워야함
    text.current.removeEventListener("mouseover", hoverEvent);
  };
}, [text]);

[SPA]
Single Page Application

  • 페이지가 하나 뿐인 어플리케이션

라우팅

  • 브라우저 주소에 따라 다른 페이지를 보여주는 것
  • SPA에서 주소를 옮기는 방식으로 사용
  • 리액트에서 라우팅 처리를 위해 react-router-dom 사용

import { BrowserRouter } from "react-router-dom";

<BrowserRouter>
<App />
</BrowserRouter>,

BrowserRouter(브라우저라우터)는 웹 브라우저가 가지고 있는 주소 관련 정보를 props로 넘겨줌

[Route 적용]
방법1: 넘겨줄 props가 없을 때
<Route path="주소[/home 처럼 /와 주소를 적음]" component={[보여줄 컴포넌트]}/>

방법2: 넘겨줄 props가 있을 때
<Route path="주소[/home 처럼 /와 주소를 적음]" render={(props) => (<BucketList list={this.state.list} />)} />

정리:
import { Route } from "react-router-dom";

render(){
  return (
    <div className="App">
      <Route path="/" exact component={Home} />
      <Route path="/cat" component={Cat} />
      <Route path="/dog" component={Dog} />
    </div>
  );
}

/cat과 /dog에는 /이 있기에 {Home} 페이지가 포함되서 나옴
exact를 적용해 제외시킴

파라미터 주는 방법
<Route path="/cat/:cat_name" component={Cat}/>
파라미터는 props로 받아올 수 있지만, useParams 훅을 이용해 받을 수도 있음

import React from "react";
import { useParams } from "react-router-dom";
const Cat = (props) => {
  const cat_name = useParams();
  console.log(cat_name);
  // console.log(props);
  return (
  	<div>고양이 화면입니다!</div>
  );
};
export default Cat;

Link 컴포넌트를 이용해 리액트 내에서 페이지 전환 가능
import { Route, Link } from "react-router-dom";

<div className="App">
  <div>
    <Link to="/">Home으로 가기</Link>
    <Link to="/cat">Cat으로 가기</Link>
    <Link to="/dog">Dog으로 가기</Link>
  </div>
  <Route path="/" exact>
  	<Home />
  </Route>
  <Route path="/cat" component={Cat}>
  	{/* <Cat /> */}
  </Route>
  <Route path="/dog">
  	<Dog />
  </Route>
</div>

Link 대신 props로 history 객체를 받아 이동 가능
props.history.push("/home");

props를 안써도 useHistory 훅을 이용하면 간단히 history 객체에 접근 가능
let history = useHistory();
history.push("/cat");
react-router-dom 버전 6부터는 useHistory 대신 useNavigate를 사용

history에 goBack을 이용하면 뒤로가기 이벤트 생성 가능
history.goBack();

Route에 주소없이 연결시 지정하지 않은 주소로 들어오는 요청 대응 가능
import { Route, Switch } from "react-router-dom";
<Route component={NotFound} />

react-router-dom 버전 6부터는 Switch 대신 Routes를 사용
component -> element로 변경

[리덕스를 이용한 상태관리]
리덕스는 여러 컴포넌트가 동일한 상태를 보고 있을 때 유용
데이터 관리 로직을 컴포넌트에서 빼면, 컴포넌트는 뷰만 관리 가능

상태 관리 주요 흐름: Store, Action, Reducer, Component
1. 리덕스 Store를 Component에 연결
2. Component에서 상태 변화가 필요할 때 Action 호출
3. Reducer를 통해서 새로운 상태값을 만듬
4. 새 상태값을 Store에 저장
5. Component는 새로운 상태값을 받아옴(props를 통해 받아오며 다시 랜더링)

리덕스는 상태관리 라이브러리, 전역 상태관리를 도와줌
리덕스는 데이터를 한 군데 몰아넣고, 여기저기에서 꺼내볼 수 있게 해줌
yarn add redux react-redux
1. State: 리덕스에서 저장하고 있는 상태값(딕셔너리 형태로 보관)
2. Action: 상태에 변화가 필요할 떄 발생(액션은 객체)
3. ActionCreator: 액션 생성 함수, 액션을 만들기 위해 사용
4. Reducer: 리덕스에 저장된 상태(=데이터)를 변경하는 함수
액션 생성 함수 호출 -> 액션 생성 -> 리듀서가 현재 상태와 액션 객체를 받음 -> 새로운 데이터 생성 -> 리턴

// 기본 상태값을 임의로 정함
const initialState = {
	name: 'mean0'
} 
function reducer(state = initialState, action) {
	switch(action.type){
      // action의 타입마다 케이스문을 걸어줌
      // 액션에 따라서 새로운 값을 리턴
      case CHANGE_STATE:
          return {name: 'mean1'};
      default:
          return false;
	}
}
  1. Store: 리덕스를 적용하기 위한 용도
    스토어에는 리듀서, 현재 App 상태, 리덕스를 위한 내장 함수가 포함됨
  2. dispatch: 액션을 발생시키는 역할을 함

[리덕스의 3가지 특징]
1. store는 1개만
2. store의 state(데이터)는 오직 action으로만 변경 가능

  • 리듀서는 가지고 있던 값을 수정하지 않고, 새로운 값을 만들어 상태를 갈아 끼움
  1. 어떤 요청이 와도 리듀서는 같은 동작을 해야함
  • 리듀서는 순수한 함수여야함
  • 파라미터 외의 값에 의존하지 않음
  • 이전 상태는 수정하지 않고 변화를 준 새로운 객체를 return 해야함
  • 리듀서는 이전 상태와 액션을파라미터로 받음

[덕스 구조]
보통 리덕스를 사용할 때는 모양새대로 action, actionCreator, reducer를 분리해 작성
(액션은 액션끼리, 액션생성함수는 액션생성함수끼리, 리듀서는 리듀서끼리 작성)
덕스 구조는 모양새로 묶는 대신 기능을 묶어 작성
(특정 기능의 action, actionCreator, reducer를 한 파일에 넣음)

[컴포넌트 리덕스 데이터]

리더스도 훅이 존재함 2개의 훅을 주로 씀

  • 데이터를 가져오는 것
  • 상태를 업데이트 할 수 있는 것

import {useDispatch, useSelector} from "react-redux";
const my_lists = useSelector((state) => state.bucket.list);
state는 리덕스 스토어가 가진 전체 데이터

const dispatch = useDispatch();
dispatch(createBucket(text.current.value));

profile
달콤살벌

0개의 댓글