🔻 만약에 게시판을 만든다고 가정했을때, 비슷한 형태의 글들을 레이아웃을 만든다고 가정해보자
이럴때 state라는 객체를 통해 useState() 함수를 사용한다.
만약 위에 있는 사진대로 useState 없이 코드를 짰다고 가정한다면
import './App.css';
function App() {
let post = '블로그 글 제목';
return (
<div className="App">
<div className='black-nav'>
<h4>블로그</h4>
</div>
<div className='list'>
<h4>글제목1</h4>
<p>2월 17일 발행</p>
</div>
<div className='list'>
<h4>글제목2</h4>
<p>2월 17일 발행</p>
</div>
<div className='list'>
<h4>글제목3</h4>
<p>2월 17일 발행</p>
</div>
</div>
);
}
export default App;
이런식으로 코드가 만들어지는데, 이것은 효율성이 떨어진다.
useState를 사용하면 훨씬 더 효율적으로 코드를 작성할 수 있다.
useState 작성하는 방법은
let [초기state, state변경할함수] = useState('보관할 자료');
이런식으로 작성을 하면된다.
만약에 위의 사진대로 state를 사용해서 작성을 하고 싶다면
import './App.css';
import { useState } from 'react';
function App() {
let [글제목, 글제목변경] = useState(['글제목1', '글제목2', '글제목3']); // 배열활용
return (
<div className="App">
<div className='black-nav'>
<h4>블로그</h4>
</div>
<div className='list'>
<h4>{글제목[0]}</h4>
<p>2월 17일 발행</p>
</div>
<div className='list'>
<h4>{글제목[1]}</h4>
<p>2월 17일 발행</p>
</div>
<div className='list'>
<h4>{글제목[2]}</h4>
<p>2월 17일 발행</p>
</div>
</div>
);
}
export default App;
이런식으로 useState에 배열을 활용하여 작성을 하면 된다
글제목[0] 옆에 좋아요 버튼을 하나 만들어서 좋아요 버튼을 누를때마다 브라우저 창에 좋아요 갯수가 하나씩 늘어나는 기능을 구현해보자!
/* eslint-disable*/
import { useState } from "react";
function App() {
let [글제목, 글제목변경1] = useState(["글제목1", "글제목2", "글제목3"]);
return (
<div className="App">
<div className="black-nav">
<h4>블로그</h4>
</div>
<div className="list">
<h4>
{글제목[0]} <span> 👍 </span> 0
</h4>
<p>2월 17일 발행</p>
</div>
<div className="list">
<h4>{글제목[1]}</h4>
<p>2월 17일 발행</p>
</div>
<div className="list">
<h4>{글제목[2]}</h4>
<p>2월 17일 발행</p>
</div>
</div>
);
}
export default App;
클릭을 할때마다 저 0부분이 1, 2, 3... 이런 식으로 숫자가 1씩 증가해주어야 하는것이니까 state로 만들어보자
let [좋아요갯수, 좋아요갯수변경] = useState(0); // state 부분 추가
<h4> {글제목[0]} <span> 👍 </span>{좋아요갯수} </h4> // 좋아요갯수 부분을 state로 지정
👍 을 클릭하면 {좋아요갯수} state가 1씩 늘어나는거니 onClick을 하면 저 state변경함수인 좋아요갯수변경()이 발생하도록 하자
<h4> {글제목[0]} <span onClick={() => {좋아요갯수변경(좋아요갯수+1)}}> 👍 </span>{좋아요갯수} </h4>
onClick= {} 안에는 무조건 함수가 들어가야하고, onClick 이벤트가 발생했을 때, 좋아요갯수변경 함수가 호출되도록 하였다. {좋아요갯수} 는 초기값이 0이 었지만, 좋아요갯수변경 함수로 인해 1씩 증가하게 된다!
<h4> <span onClick={() => {
글제목변경(['글제목1 변경', '글제목2', '글제목3']);}}> {글제목[0]} </span>
<span onClick={() => {좋아요갯수변경(좋아요갯수+1)}}> 👍 </span>{좋아요갯수} </h4>
이런식으로 작성을 해주어도 상관은 없지만, 이렇게 코드를 작성하면 확장성이 부족하다. 만약에 저 글제목들이 1000개라고 했을시에, 저 onClick안에 코드가 가독성이 떨어진다.
그렇기 때문에 스프레드문법을 사용해서 복사본을 하나 만들어준 후에, 저 [0]부분만 '글제목1 변경' 으로 바꾸어 주면 된다.
<h4> <span onClick={() => {
let copy = [...글제목];
copy[0] = '글제목1 변경';
글제목변경(copy);}}> {글제목[0]} </span>
<span onClick={() => {좋아요갯수변경(좋아요갯수<+1)}}> 👍 </span>{좋아요갯수} </h4>
밑의 코드처럼 스프레드 문법으로 복사본을 만들어주는것이 아니라 일반적으로 그냥 복사본을 하나 만든다고 하면 작동을 하지 않는다. 왜일까?
<h4> <span onClick={() => {
let copy = 글제목; // 작동안함
copy[0] = '글제목1 변경';
글제목변경(copy);}}> {글제목[0]} </span>
<span onClick={() => {좋아요갯수변경(좋아요갯수+1)}}> 👍 </span>{좋아요갯수} </h4>
이 부분을 알려면 state 변경 함수 원리와 배열 값의 원리를 알아야한다.
state 변경 함수를 사용할때, 리액트내에서 기존 state와 바뀐 state 가 같은지 먼저 검사를 해보고, 같다면 state 변경을 해주지 않는다.
또한 배열은 원시 값이 아닌 참조 값을 갖는데, 밑의 사진처럼 arr안에 [1, 2, 3]의 값이 들어가는 것이 아니라, arr이 [1, 2, 3]의 값을 가지고 있는 주소를 참조하기만 한다.
let arr = [1,2,3];
let arr2 = arr; // 새로 만들어주는 것이 아니라 똑같은 주소를 참조하고 있음.