본문 바로가기

내용 복습/Next.js

[React] state(2)

1. 양방향 바인딩

// Player.jsx

import { useState } from "react";

export default function Player({ initialName, symbol }) {
  const [playerName, setPlayerName] = useState(initialName);
  const [isEditing, setIsEditing] = useState(false);

  function handleEditClick() {
    setIsEditing(true);
  }
  
  function handleChange(event) {
    setPlayerName(event.target.value)
  }
  
  let editablePlayerName = <span className="player-name">{playerName}</span>
  // let btnCaption = 'Edit'
  
  if (isEditing) {
    editablePlayerName = <input type="text" required value={playerName} onChange={handleChange}/>
  // bntCaption = 'Save'
  }

  return (
    <li>
      <span className="player">
        {editablePlayerName}
        <span className="player-symbol">{symbol}</span>
      </span>
      <button onClick={handleEditClick}>{isEditing ? 'Save' : 'Edit'}</button>
    </li>
  );
}

 

제어하고자 하는 상태가 많을 때는 useStete를 여러 개 사용할 수 있는데, 여기서 handleChange는 변경이 함수가 반응하는 조건이다. 이 공식 이벤트는 input에서 일어나며 이용자가 input에 문자를 입력할 때마다 실행된다. 이것을 쓰려면 onChange 속성을 쓰면 된다.

여기서 중요한 점은 onChange는 매 작성값, 즉 매 keystroke(입력)에 의해 발동되고, 사용자가 작성한 내용과 동일한 이벤트 객체를 발생시킨다. 그것을 handleChange 함수에서 event라는 매개변수로 받는다. 입력값은 자동으로 넘어오게 되는데, 포인터를 넘기는 위치를 handleChange로 정의한 셈이다. 결국 리액트가 onChange라는 함수를 호출하는 것은 이 변화라는 이벤트가 발생했을 때이고 리액트가 이벤트 객체를 내보낼 때는 이 함수를 호출하여 이 함수에 대한 인수로 내보낸다.

이 테크닉을 양방향 바인딩이라고 한다.

 

양방향 바인딩: 입력값의 변화에 반응하고, 변경된 값을 다시 입력값에 전달하는 방식. 입력값에서 값을 뺴내어 다른 값을 다시 전달한다.

 

상태가 객체나 배열이라면 해당상태를 업데이트할 때, 변경불가능하게 하는 것이 좋다. 즉, 이전 상태를 복제해서 새 객체나 배열에 저장해놓고 이 복제된 버전을 수정하라.

 

이 방식이 좋은 이유는 상태가 객체나 배열이면 이는 JS내의 참조값이기 떄문이다. 그러므로 이런 방식으로 업데이트한다면 메모리 속의 기존 값을 바로 변경하게 되는데, 이 시점은 리액트가 실행하는 예정된 상태 업데이트보다 이전에 일어나게 된다. 한 객체나 배열에 여러 상태업데이트가 예정되어 있으면 부작용이 발생할 수 있기 때문에 이용된다.

 

const updatedBoard = [...prevGameBoard].map(innerArray => [...innerArray])]
prevGameBoard[rowIndex][colIndex] = 'X'

 

위의 스프레드 연산자를 담고있는 객체가 바로 그것인데, 업데이트와 동시에 모두 복사된다. 보다시피 여러 개의 스프레드 연산자로 중첩된 array도 가져올 수 있다. 이전에 저장한 데이터를 아직 가지고 있지만, 상태를 변경 불가능한 방식으로 업데이트 하는 것이다. 이를 불변객체의 상태관리라고 한다.

 

2. 상태 끌어올리기

상위 컴포넌트의 상태 변경 함수 그 자체를 하위컴포넌트로 전달하고, 이 함수를 하위 컴포넌트에서 실행하는 것을 이른다.

동일한 데이터에 대한 변경사항을 여러 컴포넌트에 반영해야 할 필요가 있을 때 쓰이며, 상태를 제어할 때 가장 가까운 부모 컴포넌트에서 하는 이유는 이 컴포넌트가 해당 정보를 필요로 하는 두 컴포넌트에 대해 접근이 가능하기 때문이다. 

 

function App () {
const [activePlayer, setActivePlayer] = useState('X')

function handleSelectSquare() {
  setActivePlayer((curActivePlayer) => curActivePlayer === 'X' ? 'O' : 'X')
}

return (
... 중간내용 ...
<GameBoard onSelectSquare={handleSelectSquare} />
)

 

이런 방식이다. 여기서는 player와 GameBoard가 같은 app 컴포넌트 내에 있고 행렬 내부의 버튼을 클릭할 때마다 player의 상태와 버튼의 상태가 동기화되어 바뀌기 때문에 사용했다.

 

이것을 사용해선 안 되는 경우가 있는데, 위의 onChange를 사용했을 때이다. onChange의 경우 타이핑될 때마다 상태가 업데이트 된다. 이 데이터를 끌어올리게 되면 상태가 업데이트될 때마다 다른 컴포넌트도 재평가되어 불필요한 리소스를 사용하게 된다. 

'내용 복습 > Next.js' 카테고리의 다른 글

[React] cookie 적용 시간 처리  (0) 2024.04.22
[React] 상태관리 라이브러리 Recoil 연습  (0) 2024.04.01
[React] State 정리(1)  (1) 2024.03.27
[React] Props(2)  (1) 2024.03.14
[React] Fragment에 대해 알아보자  (0) 2024.03.05