훅스

 

 

자바 - 멤버변수 메소드

자바스크립트 - 함수

 

함수형 프로그래밍

의존성배제

상태가 없다 (즉 멤버변수가 없다)

대신 state 를 넘겨준다 (DB에서 들고온 데이터를 state로 가져온다)

DB + 변수 + 함수파라미터 모두 동기화

 

의존성 배제

엔지니어가 가로등을 고치려면 망치와 사다리가 필요하다고 가정한다

엔지니어는 망치와 사다리에 의존적이다

 

1번가로등 고장 -> 정상

2번가로등 정상

 

이렇게 확인하여 고치는 것이 아니라 저장된 문서(DB)를 이용하여 고장확인을 하는 것

이것이 함수형

 

hooks

{useState}를 임포트해준다

0자리는 오브젝트자리

 

 

 

add 함수 추가

 

 

 

숫자가 증가한다

 

...(정규연산자)는 배열을 for문으로 뿌리는 것이라고 생각하면 됨

 

변경버튼을 누르면 비밀번호만 바뀐다

 

변수가 여러개 필요하다면 여러개 선언하면 된다

 

---------------------

함수형 컴포넌트에서 props 받으려면

괄호에 바로 넣어버리면 된다

---------------------

 

useEffect

클래스형 컴포넌트의 componentDidMount와 같다

 

 

change 함수 생성

 

여러번 눌러도 한번만 변경되고 더이상 변경되지 않는다

 

대괄호가 들어가면 최초실행시에만 콘솔로그가 뜬다

 

눌려도 렌더링 문구가 안뜬다 useEffect (초기화Constructor의 용도로 사용된다)

 

대괄호 안에 name을 넣으면

 

렌더링이 처음 + 이름변경 했을 때 한번 렌더링 문구가 뜬다

 

useEffect는 특정 값이 변경 되었을 때 캐치하고 싶은 경우!

 

숙제 = 용도 생각해보기

 

useReducer는 리덕스를 배워야한다 (상태관리)

 

----------------

 

useMemo (필수!)

axios 같은 것을 받을 때 메모에 저장

연산최적화 (shouldUpdateComponent)

 

자바스크립트의 reduce 는 누적값에 추가값을 더하거나 빼거나 처리

a는 누적값 b는 더할 값

 

e는 컨텍스트

e.target 은 input 태그

 

 

 

 

숫자를 넣을 때마다 평균값을 계산한다

렌더가 실행되면서 값 변한거있는지 찾는다

하지만 list 는 그대로라서 평균값은 그대로

 

값이 변경 되면 리렌더링 되서 괄호가있는 함수

getAverage(list)와

JSX {괄호}안에만 변경이된다

 

-----

 

memoAvg는 list 값이 변경 되었을 때만 실행하는 것

 

 

더보기
import React, { useState, useMemo } from "react";

const getAverage = (numbers) => {
  console.log("평균값 계산 중..");
  if (numbers.length === 0) return 0;
  const sum = numbers.reduce((a, b) => a + b); //
  console.log(sum);
  return sum / numbers.length;
};

const App = () => {
  const [list, setList] = useState([]);
  const [number, setNumber] = useState("");

  //useMemo(실행할함수,[변수,변수])
  const memoAvg = useMemo(() => getAverage(list), [list]);

  const onChange = (e) => {
    setNumber(e.target.value);
  };

  const onInsert = (e) => {
    const nextList = list.concat(parseInt(number));
    setList(nextList);
    setNumber("");
  };

  return (
    <div>
      <input value={number} onChange={onChange} />
      <button onClick={onInsert}>등록</button>
      <ul>
        {list.map((value, index) => (
          <li key={index}>{value}</li>
        ))}
      </ul>
      평균값: {memoAvg}
    </div>
  );
};

export default App;

 

---

useEffect와 useMemo 차이

useEffect 하나의 일이 발생했을 때 추가적인 일

useMemo 어떤 것이 변경 되었을 때 실행 (걸러주는 것 : 데이터 변경되면 실행 : ex 다운로드)

---------

+ useCallback

----------

ref는 DOM에 접근하는 유일한 방법

key는 해당 태그의 고유한 속성

useRef - 밸리데이션체크

특이한 문법

자바스크립트에서 변수만들 때 변수를 동적으로 만들고 싶을 때 

리액트에서는 값을 변수이름으로 쓸 수 있다 

-------------

 

화면시작하자마자 포커스를 주고 싶다

 

 

 

 

 

콘솔로 확인해보면 쓸 수 있는 속성들이 나온다 

 

 

 

 

커서가 가있고 배경색이 바뀌어 있다

 

 

 

 

'Web > ReactJS' 카테고리의 다른 글

리액트 // 스테이트를 훅스로 바꾸기  (0) 2020.08.05
리액트 자동완성 스니펫  (0) 2020.08.04
리액트 // 생명주기  (0) 2020.07.29
리액트 // axios / 프로미스 / async  (0) 2020.07.28
리액트 // URL파라미터 받기  (0) 2020.07.27

 

라이프 싸이클

 

클래스형 컴포넌트

함수형 컴포넌트 - 생명주기를 다룰 수 없다

 

 

컴포넌트 하나 만들어 준다

 

import React, { Component } from "react";

// 클래스형 컴포넌트
class Counter extends Component {
  state = {
    number: 0,
  };

  // 그림을 그려주는 메서드
  render() {
    // 이 공간은 2가지의 값을 컨트롤 할 수 있다
    const temp1 = this.state;
    const temp2 = this.props;

    return (
      <div>
        <h1>카운터</h1>
        <div>값: {this.state.number}</div>
      </div>
    );
  }
}

export default Counter;

 

const가 있는 것과 없는 것의 차이

데이터 1번만 받고 더 이상 새로운 데이터를 받을 필요가 없을 때 (최초 실행 후 읽기전용) 

 

값이 추후 변경 될 가능성이 있을 경우 const를 뺀다

 

render는 그림을 그려주는 함수 = setState()가 호출되거나, 최초에 객체 생성시 그림 그려줌

render 내부에서는 state와 props에 접근할 수 있음

return 내부는 JSX 문법이 들어감

 

 

import React, { Component } from "react";

// 클래스형 컴포넌트
class Counter extends Component {
  state = {
    number: 0,
  };

  add = () => {
    this.setState({
      number: this.state.number + 1,
    });
  };

  minus = () => {
    this.setState({
      number: this.state.number - 1,
    });
  };

  // 그림을 그려주는 메서드
  //render는 그림을 그려주는 함수 = setState()가 호출되거나, 최초에 객체 생성시 그림 그려줌
  //render 내부에서는 state와 props에 접근할 수 있음
  //return 내부는 JSX 문법이 들어감
  render() {
    // 이 공간은 2가지의 값을 컨트롤 할 수 있다
    // temp1 = this.state;
    // temp2 = this.props;

    return (
      <div>
        <h1>카운터</h1>
        <div>값: {this.state.number}</div>
        <button onClick={this.add}>+</button>
        <button onClick={this.minus}>-</button>
      </div>
    );
  }
}

export default Counter;

 

 

import React, { Component } from "react";
import Counter from "./Counter";

class App extends Component {
  render() {
    return (
      <div>
        <Counter />
      </div>
    );
  }
}

export default App;

 

 

 

----

 

Counter 에서 state 삭제

 

import React, { Component } from "react";

// 클래스형 컴포넌트
class Counter extends Component {
  add = () => {};

  minus = () => {};

  // 그림을 그려주는 메서드
  //render는 그림을 그려주는 함수 = setState()가 호출되거나, 최초에 객체 생성시 그림 그려줌
  //render 내부에서는 state와 props에 접근할 수 있음
  //return 내부는 JSX 문법이 들어감
  render() {
    // 이 공간은 2가지의 값을 컨트롤 할 수 있다
    // temp1 = this.state;
    // temp2 = this.props;

    return (
      <div>
        <h1>카운터</h1>
        <div>값: {this.props.number}</div>
        <button onClick={this.add}>+</button>
        <button onClick={this.minus}>-</button>
      </div>
    );
  }
}

export default Counter;

 

 

App.js 에서 state 추가하고 컴포넌트에 프롭스 넘겨주기

import React, { Component } from "react";
import Counter from "./Counter";

class App extends Component {
  state = {
    number: 0,
  };

  render() {
    return (
      <div>
        <Counter number={this.state.number} />
      </div>
    );
  }
}

export default App;

 

 

 

 

-----------

 

이렇게 사용 합시다!

 

App

import React, { Component } from "react";
import Counter from "./Counter";

class App extends Component {
  state = {
    number: 0,
  };

  add = () => {
    this.setState({
      number: this.state.number + 1,
    });
  };

  minus = () => {
    this.setState({
      number: this.state.number - 1,
    });
  };

  render() {
    return (
      <div>
        <Counter number={this.state.number} add={this.add} minus={this.minus} />
      </div>
    );
  }
}

export default App;

 

 

Counter

import React, { Component } from "react";

// 클래스형 컴포넌트
class Counter extends Component {
  // 그림을 그려주는 메서드
  //render는 그림을 그려주는 함수 = setState()가 호출되거나, 최초에 객체 생성시 그림 그려줌
  //render 내부에서는 state와 props에 접근할 수 있음
  //return 내부는 JSX 문법이 들어감
  render() {
    // 이 공간은 2가지의 값을 컨트롤 할 수 있다
    // temp1 = this.state;
    // temp2 = this.props;

    return (
      <div>
        <h1>카운터</h1>
        <div>값: {this.props.number}</div>
        <button onClick={this.props.add}>+</button>
        <button onClick={this.props.minus}>-</button>
      </div>
    );
  }
}

export default Counter;

 

----------------

 



생성자는 최초에 실행될 때만 호출 되고 값 변경시에는 렌더만 실행된다.

 

 

 

 

 

 

값이 바뀔 때마다 실행됨 (바뀔 때마다 props가 날아오기 때문)

->  함수형컴포넌트에서는 훅스 사용

 

 

 

render 직후 한 번만 호출됨

 

 

-------

 

넘어올 nextProps 와 this.props 를 비교

(아래는 !==일경우 retrun true를 해야한다 주의)

 

false로 설정하였으니 호출은 되나 값은 변경되지 않는다

 

------------------

 

 

 

 

 

 

 

 

 

 

 

https://styled-components.com/docs/basics#installation

 

styled-components: Basics

Get Started with styled-components basics.

styled-components.com

 

 

 

 

 

 

<post key={PK} id={1} title=첫 / >

key는 데이터베이스의 기본키(PK)를 넣자

리액트에 알려줘야한다

기본키를 넣으면 중간에 넣거나 할때 계산이 편하다

반복되는 컴포넌트가 있다면 넣자

 

https://velopert.com/3636

 

누구든지 하는 리액트 7편: 배열 다루기 (1) 생성과 렌더링 | VELOPERT.LOG

이 튜토리얼은 10편으로 이뤄진 시리즈입니다. 이전 / 다음 편을 확인하시려면 목차를 확인하세요. 이번에는 리액트 프로젝트에서 배열을 다루는 방법을 알아보겠습니다. 리액트에서는 배열을

velopert.com

 

 

 

 

액시오스 설치 (통신)

 

 

import React, { Component } from "react";
import Axios from "axios";

class App extends Component {
  state = {
    data: null,
  };

  onClick = () => {
    // 다운받은 json데이터를 자바스크립트 오브젝트로 변환해줌
    Axios.get("https://jsonplaceholder.typicode.com/todos/1") // get방식으로 호출
      // 콜백부분
      .then((resp) => {
        // 프로미스, 밑에꺼 실행하다가 IO가 끝나면 돌아옴
        console.log(resp);
        return;
      });
  };

  render() {
    return (
      <div>
        <h1>클릭하세요</h1>
        <button onClick={this.onClick}>클릭</button>
      </div>
    );
  }
}

export default App;

 

 

 

 

-----------

static default props 검색해보기

-------------

 

프로미스 방식

import React, { Component } from "react";
import Axios from "axios";

class App extends Component {
  state = {
    data: {
      userId: null,
      id: null,
      title: null,
      completed: null,
    },
  };

  onClick = () => {
    const { data } = this.state;
    // 다운받은 json데이터를 자바스크립트 오브젝트로 변환해줌
    Axios.get("https://jsonplaceholder.typicode.com/todos/1") // get방식으로 호출
      // 콜백부분
      .then((resp) => {
        // 프로미스, 밑에꺼 실행하다가 IO가 끝나면 돌아옴
        console.log(resp);
        this.setState({
          data: { data, ...resp.data },
        });
        return;
      });
  };

  render() {
    const { data } = this.state; // 구조분할할당

    return (
      <div>
        <div>아이디: {data.userId}</div>
        <div>제목: {data.title}</div>
        <hr />
        <h1>클릭하세요</h1>
        <button onClick={this.onClick}>클릭</button>
      </div>
    );
  }
}

export default App;

 

 

async 방식

import React, { Component } from "react";
import Axios from "axios";

class App extends Component {
  state = {
    data: {
      userId: null,
      id: null,
      title: null,
      completed: null,
    },
  };

  onClick = async () => {
    const { data } = this.state;
    // 다운받은 json데이터를 자바스크립트 오브젝트로 변환해줌
    let resp = Axios.get("https://jsonplaceholder.typicode.com/todos/1"); // get방식으로 호출
    this.setState({
      data: { data, ...resp.data },
    });
  };

  render() {
    const { data } = this.state; // 구조분할할당

    return (
      <div>
        <div>아이디: {data.userId}</div>
        <div>제목: {data.title}</div>
        <hr />
        <h1>클릭하세요</h1>
        <button onClick={this.onClick}>클릭</button>
      </div>
    );
  }
}

export default App;

 

 

결과

 

--------------

 

 

 

 

참고사이트

함수형

https://pro-self-studier.tistory.com/76

 

1. Route 와 파라미터, 쿼리

안녕하세요, 프로독학러 입니다. 이번 포스팅에서는 리액트 라우터에 대해서 좀 더 자세히 알아보도록 하겠습니다. * 포스팅의 내용은 Velopert 님의 리액트 라우터 강의를 복습한 내용이므로 Velop

pro-self-studier.tistory.com

 

클래스형

https://gongbu-ing.tistory.com/44

 

React | Router : URL로 parameter 전송하기

 이전 포스팅에서 SPA의 한계를 극복하고자 라우터를 이용하여 경로에 알맞은 컴포넌트를 불러오는 방법에 대해 공부했다. React | Router : URL로 페이지 접근하기 Single Page Application(SPA) SPA는 서버로

gongbu-ing.tistory.com

 

 

--------------

 

Nav.js

import React from "react";
import { Link } from "react-router-dom";

const Nav = () => {
  return (
    <div>
      <ul>
        <li>
          <Link to="/">홈</Link>
        </li>
        <li>
          <Link to="/about/1">어바웃</Link>
        </li>
        <li>
          <Link to="/profile">프로필</Link>
        </li>
      </ul>
    </div>
  );
};

export default Nav;

 

링크를 걸 네비게이션 바에서 /about/1 로 임의로 1을 넘겨주었다

 

 App.js

import React, { Component } from "react";
import Home from "./page/Home";
import About from "./page/About";
import Profile from "./page/Profile";
import Nav from "./components/Nav";
import { Route } from "react-router-dom";

// exact={true} 는 정확히 주소가 맞아야먄 나오도록 할 수 있다.
class App extends Component {
  render() {
    return (
      <div>
        <Nav />
        <hr />
        <Route path="/" component={Home} exact={true} />
        <hr />
        <Route path="/about/:num" component={About} />
        <hr />
        <Route path="/profile" component={Profile} />
      </div>
    );
  }
}

export default App;

 

Route 시킬 component를 About으로 세팅하고, path="/about/:num"과 같이 변수명을 num으로 지정해준다.

 

About.js

import React from "react";

const About = ({match}) => {
  return (
    <div>
      <h1>ABOUT 페이지 입니다. {match.params.num}</h1>
    </div>
  );
};

export default About;

 

About 함수형 컴포넌트에서 매개변수에 {match}를 적어주고 리턴할 내용에 {match.params.변수명}을 적어주면 입력된다.

 

 

연산을 줄이기 위해 리스트가 바뀌었는지 확인.

같으면 업데이트x

다르면 업데이트o

--------------

push pop 쓰지말것

-------------

 

새로

rcc 엔터

 

public의 index.html 에

  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>

넣고

 

App.js

import React, { Component } from "react";

class App extends Component {
  render() {
    return (
      <div>
        <nav className="navbar navbar-expand-md bg-dark navbar-dark">
          <a className="navbar-brand" href="#">
            Navbar
          </a>
          <button
            className="navbar-toggler"
            type="button"
            data-toggle="collapse"
            data-target="#collapsibleNavbar"
          >
            <span className="navbar-toggler-icon"></span>
          </button>
          <div className="collapse navbar-collapse" id="collapsibleNavbar">
            <ul className="navbar-nav">
              <li className="nav-item">
                <a className="nav-link" href="#">
                  Link
                </a>
              </li>
              <li className="nav-item">
                <a className="nav-link" href="#">
                  Link
                </a>
              </li>
              <li className="nav-item">
                <a className="nav-link" href="#">
                  Link
                </a>
              </li>
            </ul>
          </div>
        </nav>
        <br />
      </div>
    );
  }
}

export default App;

 

또는 nav를 컴포넌트 또는 함수형 컴포넌트로 만들어서 App.js에 집어넣자

 

-----------------

Next.js 꼭 써보자

----------------

리액트는 하이퍼링크 (a태그)를 쓰지 못한다.

그래서 라우터를 사용해야한다.

 

SPA 싱글 페이지 애플리케이션

리액트는 싱글페이지이다.

아래 라이브러리를 사용하자.

 

 

yarn이 아니라면 npm사이트가서 설치법 확인

 

 

설명을 보려면 빨간박스

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

부트스트랩의 A링크도 다 Link to로 바꾸면 된다.

 

 

 

 

스타일 컴포넌트는 무조건 클래스 밖으로 빼는 것을 권장한다

 

추가 concat
삭제 filter
검색 filter
반복 map
수정 map
중간요소 추가 slice + concat

스프레드 연산자 [...]

 

중간요소추가

 

1,2,3을  1,2,4,3으로 만드는 법

 

비효율적인 방법

 

 

 

짧게 하는 법!

 

 

----

스프레드 연산자

장점
1. 깊은 복사에 좋다
2. 오브젝트 결합시 같은값을 중복처리하여 바꾼다

 

 

 

----------

 

 

 

-----------

 

 

 

 

스프레드 연산자로 a 와 b를 결합 (배열일 경우!!!)

 

 

-------

 

얕은 복사

 

깊은 복사

 

----

 

 

스프레드 연산자로 오브젝트 연산시 다른 현상이 일어난다(중요)

 

데이터가 덮어씌워진다

 

 

완전히 덮어씌어진다

 

 

 

d 라는 중복이 제거된다

 

 

맨위의 중간에 추가하는 기능을 스프레드로

 

 

 

----------------

 

검색

 

 

 

 

 

 

 

 

 

---------------

수정

 

 

 

 

 

 

 

이렇게하면 모양이 망가진다

 

 

 

 

 

 

 

오브젝트 결합시 덮어씌워지고 합쳐진다.(중요)

 

----------

 

immer (불변성 관리도구 / 스프레드관련)

 

---------

 

버츄얼돔
- state의 내용 변화를 연산한다 (내용이 일치하는지 달라졌는지 전체 확인) -> 연산후 변화된 부분 렌더링
- 연산이 많아지면 느려진다
- ShouldComponentUpdate -> 연산할지 말지 결정
if(prvState.num === State.num){return false true} -- >
같은배열이면 연산X, 다른배열이면 연산O , 깊은 복사로 연산을 줄일 수 있음(불변성)

 

-----------

 

수정하기

 

더보기
import React, { Component } from "react";
import Post from "./Post";
import styled from "styled-components";

const ContainerBox = styled.div`
  display: grid;
  justify-content: center;
`;

class App extends Component {
  state = {
    posts: [
      {
        id: 1,
        title: "제목1",
      },
      {
        id: 2,
        title: "제목2",
      },
      {
        id: 3,
        title: "제목3",
      },
    ],
  };

  render() {
    const add = () => {
      // render안에 const로 만들면 계속 초기화 되지않는다
      this.setState({
        posts: this.state.posts.concat({
          id: 4,
          title: "제목4",
        }),
      });
    };

    const del = () => {
      // render안에 const로 만들면 계속 초기화 되지않는다
      this.setState({
        posts: this.state.posts.filter((post) => {
          return post.id !== 2;
        }),
      });
    };

    const update = () => {
      const data = {
        id: 2,
        title: "제목200",
      };

      this.setState({
        posts: this.state.posts.map((post) =>
          post.id === 2 ? { ...post, ...data } : post
        ),
      });
    };

    return (
      <ContainerBox>
        <button onClick={add}> 추가 </button>
        <button onClick={del}> 삭제 </button>
        <button onClick={update}> 수정 </button>
        {this.state.posts.map((post) => {
          return <Post id={post.id} title={post.title} />;
        })}{" "}
      </ContainerBox>
    );
  }
}

export default App;

 

 

내용이 변경된다

 

-------------

 

 

 

 

 

 

 

 

+ Recent posts