저번 시간에 작업한 내용으로 이제
입력 창을 열고 닫을 수 있습니다
그리고 수정 중 현재 플레이어 이름이 보이도록 했습니다
이제 이 플레이어 이름을 수정할 수 있도록 해 보겠습니다
지금은 이름을 수정하려고 하면
작동하지 않는 것을 확인할 수 있습니다
작동하지 않는 이유는
해당 값 속성을 입력 요소에
설정했기 떄문입니다
이 값 속성의 특별한 점은
입력창에서 보이는 값을 설정한다는 점입니다
이 값을 수정하려고 하면
수정이 안 됩니다
여기에 설정되어 있는 값이
변경하려는 내용을 계속 덮어쓰기 때문입니다
이 문제를 해결하는 방법으로는
특수한 기본값 속성을 설정하는 것이 있습니다
즉 초기값을 설정함으로써
이후 특정 값으로 덮어쓰지 못하게 합니다
이 작업을 마친 후에
새로고침을 해 보면
이름은 여전히 이렇게 뜨지만
이제 수정이 가능합니다
이전보다 발전이 있었습니다
하지만 '저장(Save)'을 눌러도
아직 저장은 되지 않습니다
다시 이전 이름인 플레이어 1로 돌아갑니다
그래서 다시 돌아가서 '값(value)'으로만 설정하겠습니다
여기에서는 다른 접근방식을 사용하겠습니다
단순히 값을 설정하는 것에 더해서
이용자가 적용하려고 하는
변경된 값 또한 적용시키겠습니다
변경된 플레이어 이름을 저장할 때
변경된 내용이 이 컴포넌트 안에 저장되면
이름이 변경될 때마다 변한 값을
반환하게 됩니다
즉, 상태(state)가 하나 더 필요합니다
리액트에서는 이런 작업이 가능합니다
useState를 동일한 컴포넌트 안에서 여러 번 사용이 가능한데
제어하고자 하는 상태가 많을 때 유용합니다
예시를 들어 보자면
이 상태의 초기값은 이름이 될 수 있습니다
여기 있는 이름 속성(name)에서 가져오게 됩니다
지금은 초기 이름이라는 뜻으로 initialName을 사용하겠습니다
이제 이 initialName 속성을
이 상태의 초기값으로 사용합니다
그리고 구조 분해 할당를 통해
playerName과 setPlayerName 함수를 가져올 수 있습니다
늘 그렇지만
상수의 이름은 임의로 설정하시면 됩니다
물론 그 이름이
해당 상태를 잘 설명해야 합니다
이제 이 플레이어 이름 상태를
동적인 값으로 사용하되
이 값에도 사용하겠습니다
이제 이름이 겹치는 상황이 생겼습니다
바로 이 상수와 이 변수의 이름입니다
이 변수 이름을 변경하겠습니다
여기에서는 editablePlayerName으로 변경하겠습니다
다른 이름으로 하셔도 됩니다
그리고 이 editablePlayerName을 가져와서
아래쪽에서도 이대로 반환하겠습니다
이제 playerName 상태 설정이 완료되었습니다
initialName 속성도 설정했습니다
이제 앱 컴포넌트에서도
속성 이름을 변경해야 합니다
플레이어 컴포넌트의 인스턴스(instance) 둘 다 initialName으로 변경하겠습니다
이제 플레이어 컴포넌트에서는
이 상태를 변경해야 합니다
이 상태 변경은
입력 필드에 무언가를 작성할 때마다 실행됩니다
이것을 위해 함수가 하나 필요한데
어떤 조건에 의해 실행되는 함수입니다
함수명은 handleChange로 하겠습니다
변경, 즉 change(변화)가 함수가 반응하는
조건이기 때문입니다
이 공식 이벤트(event)는
입력 필드에서 발생합니다
이것은 결국
이용자가 이 입력 필드에 문자를 입력할 때마다
실행됩니다
혹은 입력 필드에 어떤 값을 붙여넣어도
실행될 수 있겠습니다
이 이벤트에 반응하기 위해서
onChange 속성을 입력 필드에 설정해 놓겠습니다
이 속성의 값은 이제
handleChange 함수입니다
이 새로운 함수입니다
이 handleChange 함수에서는
이 setPlayerName을 호출하여 해당 상태를
이용자가 작성한 새로운 이름으로 설정하겠습니다
여기서 필요한 것은
이용자가 작성한 내용입니다
여기에서 중요한 부분은
onChange는 매 작성값, 즉 매 입력(keystroke)에 의해 발동되고
또 이벤트 객체를 제공하는데
객체의 내용은 이용자가 작성한 값이라는 점입니다
예를 들어 이용자가 키보드의
버튼을 눌렀을 때 그 값입니다
이 이벤트 객체를 받아들일 때
이벤트 매개변수로서 받게 됩니다
이 이름은 임의로 설정하시면 됩니다
어쨌든 이것은 이벤트를 묘사하는 객체가
방출된 것입니다
그리고 이 값은 자동으로 넘어오게 되는데
포인터를 넘기는 위치가
handleChange 함수이고
이 포인터는 이 입력 요소의 onChange 속성으로 넘어옵니다
리액트가 이 handleChange 함수를 호출하는 것은
이 변화라는 이벤트가 생길 때입니다
그리고 리액트가 이벤트 객체를 내보낼 때는
이 함수를 호출하여
이 함수에 대한 인수로서 내보냅니다
그러므로 이 내용은 자동으로 넘어옵니다
이 이벤트 객체는 로그(log)에 저장할 수 있습니다
이렇게 하면 직접 읽어볼 수 있습니다
하지만 이것은 .target 속성으로서
이벤트를 방출한 요소를 참조하게 됩니다
즉 이 input 요소입니다
그리고 이 input 요소는
value (값) 속성을 가지고 있는데
이 속성은 이용자가 작성하려고 한 값을 저장합니다
그 작성하려는 내용은 이후 이 값 속성을 통해 설정된
이 값으로 덮어씌워집니다
이 과정을 통해 사용자가
작성하려고 한 내용을 볼 수 있습니다
그리고 여기에서는 이 값을
플레이어 이름에 대한 새로운 상태로 설정하겠습니다
플레이어 이름을 다시 input 요소의
값 속성에 집어넣고 있기 때문에
작성된 값은 이제 input 요소에서
확인할 수 있습니다
그 이유는 이 값을 변경하는 기준이
이용자가 입력하려고 한 이 값이기 때문입니다
이 모든 작업이 끝났으므로
console.log를 삭제하겠습니다
이렇게 하면 이벤트 객체가 안 보이게 됩니다
원한다면 그대로 두셔도 됩니다
일단 이대로 모두 저장하고 새로고침을 해보면
여전히 이 초기값이 있습니다
하지만 이 이름을 MAX로 변경하면
이렇게 변경되는 것을 볼 수 있습니다
여기서 '저장'을 누르면
저장까지 할 수 있습니다
이제 이 플레이어 이름을 상태로서 제어하기 때문입니다
이 부분은 물론
플레이어 컴포넌트의 두 인스턴스 모두에게 적용됩니다
그러므로 아주 중요한 새로운 개념이라고 할 수 있습니다
이렇게 함으로써 이용자가 입력 필드에 작성한 값에
접근할 수 있는데, 이것은 onChange의 도움과
개별의 상태를 제어함으로써 가능합니다
또 이 변경된 값이 입력 필드에 다시 보여짐으로써
해당 값에 접근이 가능해집니다
필요하다면 앱의 다른 부분에서도 띄울 수 있습니다
참고로 입력값의 변화에 반응하고
변경된 값을 다시 입력값에 전달하는 방식을
양방향 바인딩이라고 합니다
이 입력값에서 값을 빼내어
다른 값을 다시 여기에 전달하기 때문입니다
이 부분은 참고만 하시고
양방향 바인딩이 무엇인지 대락적으로
이해할 수 있으시면 됩니다