State - 2

박요진·2023년 9월 3일
0

State 활용법

1. 글 수정 버튼 만들기

1-1. State를 활용법을 배우기 전에 글 수정 버튼 만들어보기

function App() {
 
  let [제목, 변경할제목] = useState( ['가시', '나무', '오렌지나무'] );
  
  return (
   	<button onClick={ () => { ??? } }> 수정버튼 </button> 
  )
}
  • 버튼을 하나 만들었습니다. 이제 저 버튼을 누르면 글이 수정되도록 하고 싶습니다. 이제 물음표 안에는 무엇을 넣어야 할까요?
function App() {
 let [제목, 변경할제목] = useState( [ '가시', '나무', '오렌지나무' ] );

	return (
      <button onClick={ () => {
      변경할제목(['선인장', '나무', '오렌지나무']);
    }> 수정 버튼 </button>
   )
}
  • 위와 같이하면 이제 기존에 들어가있던 제목 이라는 state 값이 바뀌게 됩니다. state 변경 함수는 ( ) 안에 넣은 걸로 기존 state를 갈아 치워주기 때문에 저렇게 집어넣으면 됩니다.

변경할제목('선인장') 이라고 쓰면 state 안의 값은 '선인장' 이라는 값 하나만 남게 됩니다. 만약 배열로 적었다가 위와 같이 적게 되면 모든 내용이 깨지게 됩니다.

1-2. 확장성

  • 그런데 위와 같이 코드를 짜면 코드의 확장성이 부족하게 됩니다. [ ] 안에 글이 3개 밖에 없기 때문에 할 수 있는거지 글이 100개 이상 들어있게되면 onClick 안의 코드도 매우 길어지게 될 것 입니다.
  • 기존 state를 다 복붙하지 말고, 기존 state를 첫 글자만 살짝 바꿔서 state 변경함수에 집어넣는 식으로 개발해봅시다.
function App() {
 let [제목, 변경할제목] = useState( ['가시', '나무', '오렌지나무'] );
  
  return (
    <button onClick={ () => {
   	제목[0] = '선인장';
    변경할제목(제목);
  }} > 수정 버튼 </button>
 )
}
  • 이렇게 사용할 수 있습니다. array 자료 안의 X번째 항목을 변경하고 싶을 때 array자료[X] = '바꿀값' 으로 안의 내용을 변경하고 state 변경함수에 제목 이라는 초기값을 다시 집어 넣은 것 입니다. 그런데 이 것보다도 더 좋은 방법이 있습니다.
function App() {
 let [제목, 변경할제목] = useState(['가시', '나무', '오렌지나무']);
  
  return (
    <button onClick={ () => {
    let copy = 제목;
    copy[0] = '선인장';
  	변경할제목(copy);
  } } > 수정 버튼 </button>
 ) 
}
  • array, object의 자료를 다를 때는 원본 데이터를 직접 조작하는 것 보다는 기존값은 보존해주는 식으로 코드를 작성하는 것이 좋은 관습입니다. (막상 변경했는데 원본 파일이 필요할 경우도 생길 수 있기 때문에)

  • 그래서 let copy 같은 변수에다가 기존 array를 복사해놓고 그걸 조작하는 식으로 코드를 작성하면 조금 더 안전합니다.

  • 하지만 위와 같이 코드를 작성하면 실제로는 변경되는 것이 없는 것을 확인하실 수 있습니다. 그게 State 함수의 동작원리 때문인데, 이유는 아래와 같습니다.

  • state 변경함수를 사용할 때 기존state === 신규state 이렇게 검사를 해보면 true가 나옵니다. 그러면 기존의 state와 같다는 뜻인데, 그 것 때문에 글제목 변경(copy)를 해도 변경된 값이 나오질 않는 것 입니다.

  • copy라는 변수가 기존 state와 같기 때문에 변경이 되지 않은 것 입니다.

  • copy라는 변수랑 기존 state랑 안에 있는 자료가 다른데 왜 같다고 할까요? 그 것은 array와 object의 동작원리 때문입니다.

    1-2-1. array/object 동작원리

  • 자바스크립트를 예로 들어보기 위해 array/object를 하나 만들어봅시다.

    1. let arr = [1,2,3] 이렇게 만들면 [1, 2, 3] 자료는 RAM 이라는 가상공간에 저장이되고, let arr 변수에는 그 자료가 어디있는지 가리키고 있는 화살표만 담겨있습니다.

2. 그래서 array/object 자료를 복사하면 이상한 일이 벌어집니다.

let data1 = [1,2,3];
let data2 = data1;
  • 이런식으로 사용하면 복사가 됩니다. data1에 있던 자료를 data2에 복사한다는 뜻인데, data2를 출력해보면 [1, 2, 3] 이라는 값이 잘 나옵니다.

  • 그런데 data1 과 data2는 각각 [1,2,3]이라는 데이터를 별개로 저장하는 것이 아니라 data1과 data2는 똑같은 값을 공유합니다. data1을 변경하면 data2도 자동으로 변경됩니다.

  • 왜냐하면 변수에는 화살표만 저장되기 때문입니다. 그래서 방금 한 것은 화살표를 복사한 것이고, data1 과 data2는 똑같은 화살표를 가지게 되는 것 입니다. (같은 자료를 가리킴)

3. 그래서 같은 화살표를 가지고 있는 변수끼리는 등호로 비교해도 같다고 나옵니다.

  • 그래서 처음의 자료로 돌아와서 생각해보면...
let copy = 제목;
copy[0] = '선인장';
변경할제목(copy);
  • 이렇게 코드를 작성하게 되면 컴퓨터는 copy와 기존 제목의 state를 똑같다고 생각하기 때문에 state 변경을 해주지 않습니다.

  • 그래서 해결 방법은 아래처럼 코드를 작성하면 됩니다.

let copy = [...제목];
copy[0] = '선인장';
변경할제목(copy);

4. 그럼 [...제목] 은 뭘까요?

  • spread operator 라고 하는 문법인데, array나 object 자료형 왼쪽에 붙힐 수 있는데, 뜻은 별거없고 괄호를 벗겨주세요~ 라는 뜻입니다.
  • ...[1,2,3] 이렇게 쓰면 그 자리에 1,2,3 이 남습니다. 그냥 괄호 벗기기용 연산자입니다.
    그런데 두 번째 용도도 있는데 array나 object 자료형을 복사할 때 많이 사용합니다.
let data1 = [1,2,3];
let data2 = [...data1];
console.log(data1 === data2); // false
  • data1에 있던 자료들을 괄호를 벗긴 다음에 다시 array로 다시 만들어주세요~ 라고 사용하면 화살표가 달라집니다. 새로운 array로 인식하기 때문입니다.
  • 그래서 위와 같이 하면 완전 독립적인 array 복사본을 생성해줄 수 있습니다. object 자료형도 마찬가지입니다.
    - 이런 독립적인 사본을 shallow copy 또는 deep copy라고 합니다.

오늘의 정리

리엑트에서 array/object를 수정하고 싶으면 독립적인 카피본을 만들어서 수정하는 것이 좋습니다.
[...기존state] or {...기존state} 이렇게 하면 독립적인 카피가 하나 생성됩니다.

profile
프론트엔드 개발자 지망생입니다.

0개의 댓글

관련 채용 정보