- React

hooks 라이브러리 - useState

나둥식 2022. 11. 2. 01:24

1️⃣ 상태값을 변경해서 UI 동기화하기 (⭐ React 안에 hooks 라이브러리 사용 )

① 함수와 변수 만들고 뿌려보기

let number = 1;
const add = () => {
number++;
console.log('add', add);
};

return (
    <div>
      <div>
        <h1>숫자 : {number}</h1>
      </div>
    </div>
  );

 

② 버튼 만들기

return (
    <div>
      {/* <div style={mystyle}>안녕{a === 10 ? '10입니다.' : '10이 아닙니다.'}</div>
      <h1 className="box-style">해당태그{b === 20 && '20입니다.'}</h1> */}
      <h1>숫자 : {number}</h1>
      <button>더하기</button>
    </div>
  );

 

 

③ 더하기 버튼을 클릭하면 number 값을 변경하기

: onClick 함수 사용

<button onClick={add}>더하기</button>

➡ 함수를 넣을 때, add() 괄호를 넣지 말고 바인딩만 하기!  ()를 넣으면 실행이 됨

➡ 버튼 클릭 시, console에는 찍히지만 상태 ui가 변경되지 않음! 

⭐ 랜더링 시점 = 상태값 변경시

 

 

④ 코드 수정 - useState 사용

// let number = 1; // 상태 값 아님
const [number, setNumber] = useState(1);

- 변수는 number로 변경하는데, 이 변수를 변경하려면 setNumber로 변경해야 함

- useState(1)의 1이 number에 들어옴

- useState(2)로 변경하면 숫자:2로 변경됨

 

 

⑤ 더하기 버튼을 클릭하면 setNumber()를 호출하기

const add = () => {
    setNumber(number + 1); // 리액트한테 number값 변경할게!라고 요청하는 것
    // ++은 자기한테 다시 값을 넣는거라 안됨
    console.log('add', number);
  };

==> const [number, setNumber]의 number가 상태값이 됨! ( = UI와 동기화되었다. )

⭐ 상태 값을 만들어서 setNumber로 호출할때만 return이 된다.

 

 

 

⑥ 전체코드

const [number, setNumber] = useState(1);

  const add = () => {
    setNumber(number + 1); // ++은 자기한테 다시 값을 넣는거라 안됨
    console.log('add', number);
  };

  return (
    <div>
      <h1>숫자 : {number}</h1>
      <button onClick={add}>더하기</button>
    </div>
  );

 

 

 

2️⃣ 분리하기 (컴포넌트화)

💡 rsc 치면 코드 자동완성 됨 (feat. Sub.js)

import React from 'react';

const Sub = () => {
    return (
        <div>
            <h1>Sub입니다.</h1>
        </div>
    );
};

export default Sub;

 

① App.js에 호출

return (
    <div>
      {/* <div style={mystyle}>안녕{a === 10 ? '10입니다.' : '10이 아닙니다.'}</div>
      <h1 className="box-style">해당태그{b === 20 && '20입니다.'}</h1> */}
      <h1>숫자 : {number}</h1>
      <button onClick={add}>더하기</button>
      <Sub/>
    </div>
  );

<Sub/> 만 적어주면 됨!

  • 상태가 변경되면 전체가 리빌드 됨 ( = return 다시 실행됨)
  • Sub.js는 App의 자식으로, 다시 그려질 필요가 없기 때문에 return을 막아줘야 한다. ==> 컴포넌트화

 

⭐ 리액트는 컴포넌트 설계를 잘해야 함!!! ⭐

 

 

 

✅ 문제풀이

📃 문제
: 다운로드 버튼을 클릭하면 users에 값 넣기
users 데이터를 상태로 관리하고 싶음!

 

1️⃣ 문제1

import { useState } from 'react';
import './App.css';

function App() {
  // 다운로드 받음 -> user데이터를 상태로 관리하고 싶음
  const [users, setUsers] = useState([]);

  const download = () => {
    let sample = [
      { id: 1, name: '홍길동' },
      { id: 2, name: '임꺽정' },
      { id: 3, name: '장보고' },
      { id: 4, name: '이순신' },
    ];

    // 다운로드 버튼 클릭하면 users에 값 넣기
    setUsers(sample); // 여기에 sample을 넣을 수 없음
  };

  // 랜더링 시점 = 상태값 변경
  return (
    <div>
      <button onClick={download}>다운로드</button>
      {users.map(user => <h1>{users.id},{users.name}</h1>)}
    </div>
  );
}

export default App;

➡ 다운로드 버튼을 클릭하면 sample이 나타남

 

 

2️⃣ 문제2 - 만약에, 최초에 값이 있는 상태에서 다운로드를 클릭하면 return이 된걸까?

import { useState } from 'react';
import './App.css';

function App() {
  // 다운로드 받음 -> user데이터를 상태로 관리하고 싶음
  console.log('App 실행됨');
  const [users, setUsers] = useState([
    { id: 1, name: '홍길동' },
    { id: 2, name: '임꺽정' },
    { id: 3, name: '장보고' },
    { id: 4, name: '이순신' },
  ]);

  const download = () => {
    // 기존 데이터 세팅
    let sample = [
      { id: 1, name: '홍길동' },
      { id: 2, name: '임꺽정' },
      { id: 3, name: '장보고' },
      { id: 4, name: '이순신' },
    ];

    // 다운로드 버튼 클릭하면 users에 값 넣기
    setUsers(sample); // 여기에 sample을 넣을 수 없음
  };

  // 랜더링 시점 = 상태값 변경
  return (
    <div>
      <button onClick={download}>다운로드</button>
      {users.map((users) => (
        <h1>
          {users.id},{users.name}
        </h1>
      ))}
    </div>
  );
}

export default App;

➡ 똑같은 데이터지만 래퍼런스가 다른게 setUsers에 들어갔기 때문에 실제로 한번 더 실행됨!

 

 

 

3️⃣ 문제3 - sample을 바깥에 만들어서 return되는지 알아보기

import { useState } from 'react';
import './App.css';

function App() {
  // 다운로드 받음 -> user데이터를 상태로 관리하고 싶음
  console.log('App 실행됨');

  let sample = [
    { id: 1, name: '홍길동' },
    { id: 2, name: '임꺽정' },
    { id: 3, name: '장보고' },
    { id: 4, name: '이순신' },
  ];

  const [users, setUsers] = useState(sample);

  const download = () => {
    // 기존 데이터 세팅
    
    // 다운로드 버튼 클릭하면 users에 값 넣기
    setUsers(sample); // 여기에 sample을 넣을 수 없음
  };

  // 랜더링 시점 = 상태값 변경
  return (
    <div>
      <button onClick={download}>다운로드</button>
      {users.map((users) => (
        <h1>
          {users.id},{users.name}
        </h1>
      ))}
    </div>
  );
}

export default App;

➡ 최초의 데이터와 변경되는 데이터의 값과 래퍼런스가 같음!

❗ 한 번만 실행되고, 다운로드 버튼을 클릭하면 실행이 안됨! (래퍼런스 변경이 없어서)

 

 

 

4️⃣ push로 추가하기

import { useState } from 'react';
import './App.css';

function App() {
  // 다운로드 받음 -> user데이터를 상태로 관리하고 싶음
  console.log('App 실행됨');

  let sample = [
    { id: 1, name: '홍길동' },
    { id: 2, name: '임꺽정' },
    { id: 3, name: '장보고' },
    { id: 4, name: '이순신' },
  ];

  const [users, setUsers] = useState(sample);

  const download = () => {
    // 기존 데이터 세팅
    sample.push({ id: 5, name: '조자룡' });
    console.log(sample);

    // 바뀐 데이터를 setUsers에 적용하고 싶은데 될까?
    setUsers(sample);
  };

  // 랜더링 시점 = 상태값 변경
  return (
    <div>
      <button onClick={download}>다운로드</button>
      {users.map((users) => (
        <h1>
          {users.id},{users.name}
        </h1>
      ))}
    </div>
  );
}

export default App;

sample 데이터는 바꼈지만(sample은 계속 생성되지만), 실행 안됨!

➡ 이유는? 불변 연산자이기 때문..!

 

 

 

5️⃣ concat을 사용하고 새로운 변수를 생성하면 실행 됨!

const download = () => {
  // 기존 데이터 세팅
  const a = sample.concat({ id: 5, name: '조자룡' });
  setUsers(a);
};

실행할때마다 기존 sample 데이터는 불변(변하지 않았음)이고, 같은 데이터 a가 계속해서 들어가는 것이므로 ui가 변경되지 않음!

( a가 불변이 아니면 클릭할때마다 추가가 되어야 함)

 

 

 

6️⃣ 새로운 데이터를 추가하는 간단한 방법! (전개연산자 사용)

const download = () => {
  // 기존 데이터 세팅
  setUsers([...sample, { id: 5, name: '조자룡' }]);
};

➡ 클릭할때마다 App 실행되고 추가가 됨!!

 

 

⭐ 래퍼런스가 변경되어야 동작한다.⭐