[React] State와 useState

sm·2023년 1월 12일
0

Web

목록 보기
18/24

REACT 수업 전 세팅!

Formatting / Linting / Typescript

  • Formatting
    • Code의 스타일을 통일 - 가독성
    • Prettier 대부분 사용 - 패키지 모듈로 설치해서 사용하기
npx create-react-app 230105 
//명령어 + 만들 폴더 이름
-----
npm install --save-dev prettier
//개발용으로만 사용하는 모듈 설치-배포하고 운영 X => devDependencies: "prettier" 추가
<=> npm i -D prettier
  • .prettierrc 파일을 만들어서 rule을 json 형태로 만들면 prettier가 참고를 해서 formatting
json
.prettierrc
{
    "semi": true, //세미콜론 추가
    "singleQuote": true //단따옴표
}
  • .vscode folder / settings.json
{
    "[javascript]": {
        "editor.maxTokenizationLineLength": 2500,
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    }
}

Linting: formatting에 가깝지만 더 많은 규약과 규율을 검사해주는 방법

(사장님 같은 존재 - 자잘한 잘못을 수정할 수 있다. 문법적 오류 점검)

  • Airbnb의 ESLint가 유명
  • 확장프로그램 ESLint 설치
npm i -D eslint
--
npm i -D eslint-config-airbnb-base eslint-plugin-import
  • eslintrc.js 파일 생성
module.exports = {
  extends: ['airbnb-base'],
  rules: {
    'linebreak-style': 0,
    'no-console': 'off',
  },
};

Typescript 틀만, 문법은 나중에 (이제는 필수)

  • 문법, 포맷팅도 맞는 경우, 자료형도 확인해주는 TS ⇒ 협업, 문법적 오류 ↓
  • 자료형, 형변환 정확하게 규정
npm i -D typescript
---
//@ts-check
주석을 추가하면 간단하게 타입스크립트적 체크 가능
실제 타입스크립트는 .ts파일로 다른 방법으로 사용해야 한다. 추후 배울 에정

State

  • 리액트에서 컴포넌트에 대한 상태
  • State가 변경되면 해당 컴포넌트는 바로 다시 렌더링되기 때문에 컴포넌트의 유동성 관리 쉬움

useState

  • state를 활용하면 훨씬 쉽게 변경 사항을 HTML에 반영할 수 있다.
import {useState} from "react";

const [스테이트이름, 스테이트변경함수명] = useState(초기값);
const [state, setState] = useState(iniitialState);
  • 먼저 상태를 관리하는 state를 배열의 첫번째, 해당 state를 변경할 수 있는 함수를 두번째로 지정
  • useState의 ()안에는 state의 초기값을 넣어준다.

useState 동작 원리

  • state 가 이전 값과 달라지면 해당 컴포넌트는 다시 렌더링한다.
  • 상태변경함수로 변경을 해야만 React가 state변경을 알아차리고 html을!!!! 리렌더링해준다!!
function App() {
  let [teacher, setTeacher] = useState('소미주');

  function customSetTeacher(name) {
    setTeacher(name);
    console.log(teacher);
  }

  return (
    <div className="App">
      <button onClick={() => customSetTeacher('SMJ')}>영어로!</button>
  /////이렇게 쓰면 문제 없음<button onClick={customSetTeacher}>영어로!</button>
  //위에 function을 이렇게 선언한다면, 
	// function customSetTeacher() {
				  //setTeacher("SMJ");
				  //console.log(teacher);
  //}
      <br />
      <span>{teacher}</span>
    </div>
  );
}
  • 주의사항 상태 변경함수는 꼭 함수 정의를 하고 사용!!!
    • Return 내부에서 함수 정의를 하지 않고 바로 상태 변경 함수를 호출하면 클릭이 안되어도 실행이 되기 때문에 무한 루프에 빠지게 된다.
    • State가 변경되면 당연히 return 내부에 있는 요소를 다시 렌더링해야 하니 return을 호출 → 다시 상태 변경 함수 호출 → return 호출의 무한 루프
    • 확장프로그램 ES7+ React/Redux/React-Naive snippets 설치
      • rfc ⇒ 리액트 기본 코드를 바로 쓸 수 있다.

3항 연산자 사용하기!

  • state를 변경하면 컴포넌트가 리렌더링 된다.
//단순한 조건문은 if 말고 삼항연산자
//return 안에서 if문 쓰는 것을 리액트가 막는다. 
{value > 10 ? '😎' : '👍'}

클래스형 컴포넌트의 state

  • 클래스에서 사용하는 생성자에 State값 지정
  • this.state라는 객체에 변경하고자 하는 값을 저장한다.
    • 단 state는 반드시 객체로 지정해서 사용
    • this.setState 메소드를 이용하여 this.state라는 객체에 저장된 값을 변경한다.

//구조분해 할당***


State와 변수!

  • State vs. Variable
  • 컴포넌트가 re-rendering ⇒ variable = 0인 코드가 읽혀서 ⇒ 1이 최대값이 된다.
    • 하지만 state는 이전값을 기억하고 있다.
  • State가 변경되면 해당 state 를 정의한 컴포넌트가 다시 랜더링, 함수가 다시 읽혀지면 변수는 다시 지정된다.

State 사용시 주의사항

  • 객체 또는 배열을 State로 사용할 때 매우 주의새롭게 배열을 만들어서 메모리 주소를 바꾸자.
  • 또는 배열을 만들고 전개 연산자 사용 ⇒ 값만 동일하고 주소값은 다른 새로운 배열이 만듦 […state]
  //state는 배열이 시작하는 **메모리 주소값**을 가지고 있다.
  //아무리 배열 값을 변경하려고 해도 변경되지 않는다.
  //메모리 주소는 항상 동일 => 바뀐게 없으니 렌더링이 되지 않는다.

자바스크립트 자료형

원시 타입 vs 객체 타입 ⇒ Object, Array

  • 원시타입의 경우 location에는 값이 저장되어 있지만,
  • 객체타입의 location : 메모리 주소가 들어가 있다!
export default function ArrayState() {
  const [state, setState] = useState([0]);
  console.log(state);

  return (
    <div>
      {state[0]}
      <br />
      <button
        onClick={() => {
          state[0] = 1;
          const copyArr = [...state];
          setState(copyArr);
          console.log(state);
        }}
      >
        +1
      </button>
    </div>
  );
}

결론

  • 자주 값이 변경되고 변경 사항을 바로 바로 보여줘야 하면 State로 선언
  • 배열 또는 객체로 쓰기 보다는 하나의 원시 값으로 쓰는 것이 좋다.
  • 배열 또는 객체로 사용해야 한다면, JS 객체 타입 데이터의 특성 잘 생각해야.

전개 연산자

const array = [1, 2, 3, 4, 5];
console.log(array); //[ 1, 2, 3, 4, 5 ]
console.log(...array);//1 2 3 4 5

const copyArr = array; //메모리 주소가 copy
console.log(copyArr); //[ 1, 2, 3, 4, 5 ]

console.log(array === copyArr); //메모리 주소가 같기 때문에 true
---
const copyArr = [...array]; //주소를 가져오는 것이 아니라 값을 가져오는 새로운 배열
console.log(copyArr);//[ 1, 2, 3, 4, 5 ] 값은 동일

console.log(array === copyArr); //false!!!
---------------------

const obj = {
  pororo: '뽀로로',
  lupy: '루피',
  crong: '크롱',
};

const copyObj = obj;

console.log(obj);//{ pororo: '뽀로로', lupy: '루피', crong: '크롱' }
console.log(copyObj); //{ pororo: '뽀로로', lupy: '루피', crong: '크롱' }
console.log(obj === copyObj); //true
---
const copyObj = { ...obj };

console.log(obj);//{ pororo: '뽀로로', lupy: '루피', crong: '크롱' }
console.log(copyObj);//{ pororo: '뽀로로', lupy: '루피', crong: '크롱' }
console.log(obj === copyObj); //false 값은 같지만 실제 메모리주소는 다르기 때문에 false

---
const copyObj = { ...obj, lupy: 'lupy' };
**//값을 하나만 변경하고 싶을 때**
//{ pororo: '뽀로로', lupy: 'lupy', crong: '크롱' }

---
//전개연산자 - 나머지 연산자로도 많이 사용
//내가 원하는 값만 , 나머지는 그대로 두고 싶을 때
function foo(a,b, ...rest) {
    
}
profile
📝 It's been waiting for you

0개의 댓글