이번 시간에는 이 입력값에 대한 유효성 검사를 해서
유효하지 않은 값을 넣고 저장을 누르면
에러 메시지를 띄우겠습니다
그렇게 하려면 우선
이 입력값이 있는 프로젝트 컴포넌트에 가겠습니다
값을 추출하는 위치도 여기인데
그 값에 대한 유효성 검사를 하겠습니다
상당히 단순하게 할 텐데
입력된 제목에서
필요없는 공백을 제거하기 위해서 trim을
시작과 첫 부분에 사용했을 때
그것이 빈 문자열과 동일하다고 한다면
값이 유효하지 않은 것입니다
비어있는 값이기 때문입니다
이 조건을 충족할 때 모달(modal)을 띄우겠습니다
하지만 에러 모달을 띄우는 조건은
이 한 가지가 아닙니다
예를 들어 제목이 비었거나
혹은 상세 내용이 비었어도 에러 메시지를 띄워야 합니다
그래서 여기에 같은 내용을 반복하겠습니다
날짜가 비어있어도 마찬가지입니다
날짜가 비었어도 모달이 필요합니다
이 세 가지 경우에 에러 모달을 띄우겠습니다
우선 모달이 필요하므로
새로운 컴포넌트를 만들겠습니다
파일 이름은 모달(Modal.jsx)로 하겠습니다
Error Modal이라고 하지 않는 이유는
이론상으로는 여기 있는 모달로
다른 정보를 보여줄 수도 있기 때문입니다
모달 파일로 돌아와서
모달 함수를 내보내겠습니다
그 안에 반환값으로 내장 대화상자 요소를 쓰겠습니다
우선 이 모달 컴포넌트가 최대한
유연했으면 합니다
그러니 여기서 모든 컴포넌트에 전달한
자식 속성을 추출하여
어떤 내용이든지 이 모달을 사용해서
감쌀 수 있도록 작업하겠습니다
이렇게 하면 그 내용은
빌트인 대화상자로 감싸게 됩니다
하지만 그게 다가 아닙니다
리액트가 제공하는 포털 기능을 사용하여
이 대화상자 및 대화상자로 감싼 내용을
DOM의 다른 위치에
렌더링하도록 하겠습니다
이 프로젝트에서 그 작업을 하려면
인덱스 파일(Index.html)로 가서
이 modal-root 디브(div)로 가겠습니다
포털 기능을 사용해서 이 디브를 렌더링하려면
createPortal을 react-dom에서 가져와야 합니다
그 다음에는 간단히
이 createPortal을 사용하여 jsx코드를 감싸고
그리고 두 번째 값으로 이 내용이 렌더링 될 위치에
HTML 요소를 전달하겠습니다
이 작업을 위해 브라우저 API를 사용하겠습니다
document.getElementByID를 써서
modal-root를 ID로 받는 이 디브를 선택하겠습니다
그 내용을 여기에 가져오면
유연한 모달이 완성되었습니다
이제 더 유연하고 재사용하기에 더 좋아졌으니
이 대화상자를 열 때
함수를 호출하도록 하되
그 함수는 커스텀 컴포넌트가 노출하도록 해서
이 함수가 호출 컴포넌트를 필요로 하지 않게 하겠습니다
즉 이 모달을 사용하는 다른 컴포넌트를 사용해서
대화상자가 내부적으로 사용되는지 여부를 아는
그런 정보는 제 모달을 쓰는 컴포넌트에게
꼭 필요한 정보는 아닙니다
그리고 리액트가 제공하는 두 가지 기능인
forwardRef 기능과
useImperativeHandle hook을 이용하여
이와 같이 유연하고 재사용 가능한
컴포넌트를 만드는 법을 배울것입니다
forwardRef부터 시작하겠습니다
모달 컴포넌트가 참조를 받을수 있어야 하기때문에
컴포넌트 함수를 이
이렇게 forwardRef로 감싸야 합니다
그리고 다른 상수나 변수에 저장해아 하는데
이것을 여기로 내보내겠습니다
이것으로 알 수 있는 것은
이 모달 컴포넌트 함수가
추가 매개변수를 얻었다는 것입니다
그것이 컴포넌트 바깥에서 설정될 수 있는
참조가 될 것입니다
그게 첫 번째 단계입니다
이제 이 컴포넌트 밖에서 호출된
함수를 노출하려면
useImperativeHandle을 사용해야 합니다
이 훅에는 여기에서 받는 참조를
전달하겠습니다
그러니까 여기있는 참조가
useImperativeHandle으로 전달된 것입니다
두 번째 값으로는 리액트가 호출할
함수가 필요합니다
여기에서는 반환하는 객체가
다른 컴포넌트로 속성이나 함수를
노출하게 됩니다
예를 들면 open 메소드입니다
이 open 메소드에서는
대화상자 쪽의
내장 대화상자 컴포넌트에서 제공하는
Show modal 메소드를 호출합니다
그러니 이제 여기서 useRef 훅을 사용 가능한데
이것도 가져와서
여기 대화상자 참조를 받아야 합니다
그리고 이것을
특수 참조 속성을 통해 대화상자 요소에 연결합니다
이제 이 open 메소드에서
dialog.current.showModal을 전달하겠습니다
이제 showModal은
내장 대화상자 요소가 공급한 메소드입니다
하지만 open은 이제 우리의 컴포넌트가 다른 컴포넌트에
제공하는 메소드입니다
그러니 이제 NewProject 컴포넌트에선
이 모달 컴포넌트를 사용한
에러 모달을 보여줄 수 있습니다
그러니 이 디브를 감싸는 프래그먼트를 추가하고
그리고 새로 만든 모달 컴포넌트도 추가하겠습니다
물론 이것은 모달 파일(Modal.jsx)에서 가져와야 합니다
이제 이 모달을 참조에 연결시킬 수 있습니다
그러니 여기에 새로운 참조를 추가하겠습니다
NewProject 컴포넌트에 추가한 모달 참조는
모달 컴포넌트에 연결될 것입니다
이제 커스텀 컴포넌트에
참조 속성을 추가하겠습니다
여기서 참조를 전달하기 때문에 가능한 작업입니다
그리고 지금 추가한 속성을
모달로 설정하겠습니다
이제 이 참조는 위쪽에 있는 유효성 검사 코드에 사용 가능합니다
Modal.current를 불러오고
이곳에 저장된 값은
우리만의 컴포넌트 함수가 됩니다
정확히 말하면 여기 이곳에 있는 객체입니다
이 객체에 노출된 모든
함수와 속성이 포함되어 있습니다
이번 경우엔 open 메소드입니다
이제 여기에 open을 불러와서
모달을 열 수 있습니다
그 다음 return을 사용하겠습니다
그러면 이 다음에 있는 코드, 즉 이 onAdd 코드가 만약
이 if 블락 코드까지 갔다면 실행되지 않습니다
즉 유효하지 않은 입력값을 받은 경우입니다
그러니 우리에게 유효하지 않은 입력값이 있다면
이 모달이 보여집니다
이제 기억해야 할 것은
이 OOTB 모달은 자주 보이지는 않고
그저 감싸는 용으로 사용됩니다
그러니 이 NewProject 컴포넌트에서 보여주고 싶은 컨텐츠를
새로 감싸야 합니다
그러니 여기에 h2 요소를 추가하여 무효한 입력값이라고 하고
그리고 그 밑에 문단을 추가하겠습니다
'이런... 값 입력을 잊으신 것 같습니다'
그리고 문단을 또 추가해서
'모든 칸에 유효한 값을'
'입력하셨는지 확인해주세요'라고 하겠습니다
그리고 이 모달을 닫기 위해
그러려면 모달 컴포넌트로 돌아가서
자식 속성 밑으로 가겠습니다
여기에 form을 추가하여
메소드를 대화 상자로 설정하겠습니다
그러면 이것으로 대화상자를 닫을 수 있습니다
이 안에 버튼을 추가하면 이 양식을 제출할 것이고
남은 일은 브라우저가 알아서 하게 됩니다
여기에는 '닫기'라고 쓰겠습니다
이 모달도 조금 더 재사용에 용이하게 할 수 있습니다
즉 창을 닫기 위해 코드를 직접 작성하지 않고
이 버튼에 대한 라벨을 받으면 됩니다
예를 들면 여기 모달 컴포넌트에서
buttonCaption 속성을 받아서
여기에 buttonCaption을 값으로 사용하면 됩니다
그렇게 하고 새 프로젝트 파일로 돌아와서
그 buttonCaption 속성을 모달에 추가하여
'닫기'나 '확인'으로 설정하겠습니다
이렇게 작업을 마치면
이 버튼을 가진 양식이
그것이 속한 대화상자를 닫게 됩니다
그 때 이 메시지를 사용하게 됩니다
이제 저장하겠습니다
여기로 돌아와서 빈 입력값을 저장하려고 하면
이런 모달을 보게 됩니다
아주 훌륭한 모양은 아닙니다만
제대로 작동이 되는 것을 확인할 수 있습니다