hooks 라이브러리 - useState
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 실행되고 추가가 됨!!
⭐ 래퍼런스가 변경되어야 동작한다.⭐