리액트

리액트>state 수정

연습노트 2024. 7. 11. 17:17

일단 글수정 버튼 만들기 

 

설명하다
 
function App(){
  
  let [글제목, 글제목변경] = useState( ['남자코트 추천', '강남 우동맛집', '파이썬 독학'] );  
  
  return (
      <button onClick={ ()=>{ ??? } }> 수정버튼 </button>
  )
}

대충 아무데나 버튼하나 만들고 이거 누르면 첫 글이 수정되는 기능을 만들어봅시다.

저기 물음표안에 뭘 넣어야하죠? 

 

 

 

 

 

설명하다
 
function App(){
  
  let [글제목, 글제목변경] = useState( ['남자코트 추천', '강남 우동맛집', '파이썬 독학'] );  
  
  return (
    <button onClick={ ()=>{ 
      글제목변경(['여자코트 추천', '강남 우동맛집', '파이썬 독학'])
    } }> 수정버튼 </button>
  )
}

이러면 숙제 끝입니다. 버튼누르면 첫 글제목 바뀜 

state 변경함수는 ( ) 안에 넣은걸로 기존 state를 갈아치워주니까 저렇게 집어넣으면 됩니다.

 

 

Q. 글제목변경('여자코트 추천') 이건 왜 안됩니까

A. 기존 state를 갈아치워준다니께요 

['남자코트 추천', 강남 우동맛집', '파이썬 독학'] 이걸

['여자코트 추천', 강남 우동맛집', '파이썬 독학'] 이걸로 바꾸고 싶으면 

['여자코트 추천', 강남 우동맛집', '파이썬 독학'] 이걸 state변경함수에 넣어야지 글 하나만 넣으면 되겠습니까 

 

 

 

 

 

 

 

약간 프로그래머 스타일로 다시만들어보면

 

지금 코드는 확장성이 부족합니다. 

[ ] 안에 글이 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를 복사해놓고 

그걸 조작하는 식으로 코드짜면 조금 더 안전합니다. 

 

근데 사기인듯 수정버튼 눌러도 안바뀌는데요

 

 

 

 

 

 

설명하다
 
function App(){
  
  let [글제목, 글제목변경] = useState( ['남자코트 추천', '강남 우동맛집', '파이썬 독학'] );  
  
  return (
    <button onClick={ ()=>{ 
      let copy = [...글제목];
      copy[0] = '여자코트 추천';
      글제목변경(copy)
    } }> 수정버튼 </button>
  )
}

이러면 제대로 동작합니다.

근데 동작원리가 궁금하지않습니까

동작원리같은거 많이 알고 있으면 나중에 혼자 코드짤 때 많은 응용이 가능합니다.

 

 

 

 

 

 

state 변경함수 동작원리 

 

state 변경함수를 쓸 때

기존state === 신규state 이렇게 먼저 검사해봅니다.

그래서 같으면 state 변경을 해주지 않습니다. 

그래서 위 코드에서도 글제목변경(copy) 해도

copy라는 변수가 기존state와 같아서 변경을 안해준 것입니다. 

 

 

Q. 잉 copy라는 변수랑 기존 state랑 안에 있는 자료가 다른데 왜 같다고함 

기존 state는 '남자코트 추천'

copy에는 '여자코트 추천'이 들어있지만

실은 기존state === copy 비교해보면 같다고 나옵니다.

왜냐고요? 

 

 

 

 

 

 

array/object 동작원리 

 

 

 

1. 자바스크립트는 array/object 자료를 하나 만들면

예를 들어서 let arr = [1,2,3] 이렇게 만들면 

[1,2,3] 자료는 램이라는 가상공간에 몰래 저장이 되고

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 data1 = [1,2,3];
let data2 = data1;  //복사
data2[0] = 1000;  //data2 내부 변경
console.log(data2 === data1)   //true 나올듯 

그렇습니다.

자세한건 javascript reference data type이라고 검색해보면 추가학습 가능합니다. 

 

 

 

 

let copy = 글제목;
copy[0] = '여자코트 추천';
글제목변경(copy)

그래서 아까처럼 이렇게하면

컴퓨터는 copy와 기존 글제목 state는 똑같다고 생각하기 때문에 (화살표가 똑같아서)

state 변경을 안해줍니다. 

 

 

 

let copy = [...글제목];
copy[0] = '여자코트 추천';
글제목변경(copy)

이러면 잘됩니다. 화살표가 달라지는 문법이라 그렇습니다. 

 

 

 

 

저기요 점3개 뭐임

 

 

 

 

 

오늘의 정리 

 

리액트에서 array/object state를 수정하고 싶으면 

독립적인 카피본을 만들어서 수정하는게 좋습니다. 

[...기존state] 

{...기존state} 

이렇게 하면 독립적인 카피가 하나 생성됩니다.

 

응용문제 : 가나다순 정렬버튼과 기능 만들기


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


function App(){
  let [글제목,글제목변경] = useState(['남자 코트 추천','강남 우동맛집','파이썬독학']);
  let [ 따봉, 따봉변경 ] = useState(0);
  let posts = '강남 우동 맛집';
  return (

    <div className="App">
      <div className="black-nav">
        <h4>ReactBlog</h4>
      </div>
 
 
      <button onClick={ ()=>{
      let copy = [...글제목];
      copy.sort((a, b) => b.localeCompare(a)); // 역순 정렬을 위한 비교 함수
      글제목변경(copy)
    } }> 역순 정렬버튼 </button>


       <button onClick={ ()=>{
      let copy = [...글제목];
      copy.sort();
      글제목변경(copy)
    } }> 정렬버튼 </button>
 
     

      <button onClick={ ()=>{
       let copy = [...글제목];
        copy[0] = '여자코트 추천'
        글제목변경(copy);
        }} > 글수정</button>



      <div className="list">
        <h4>{글제목[0]}
        <span onClick={ ()=>{ 따봉변경(따봉 = 따봉 +1) } } >👍</span>
        { 따봉 }</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;