0. props vs state
쉽게 말해서 props는 해당 컴포넌트 내에서 바꿀 수 없으며, state는 바꿀 수 있다.
또한,
state는 내부적으로 쓴다.
외부에서는 props를 통해 컴포넌트를 만진다.
이 모든 것은 DOM에 영향을 주어 UI에 변화를 준다.
결론은...props와 state를 적절하게 이용해야 한다는 의미이다.
지금까지는 read가 되는 페이지를 만들었는데, 이제 write를 통해 동적으로 페이지를 유저가 바꾸는 앱을 만들어보자!!
두둥!!
1. create 구현 : 소개
모든 정보는 CRUD 안에 있다고 한다.
Create, Read, Update, Delete를 의미하는데, 우리는 이미 read를 해보았다.
create, update, delete라는 버튼을 추가할 것이다.
create라는 버튼을 누르면?
mode가 create로 바뀌고, Content->CreateContent로 바뀐다.
사용자가 input할 수 있는 form이 추가된다.
submit을 누르면, 추가하려는 객체가 state의 contents에 항목이 추가된다.
추가된 항목을 누르면 mode를 read로 바꾸고, 내용을 보여준다.
를 만들어 보자!!
2. create 구현 : mode 변경 기능
이제 TOC와 Content 사이에, create와 read, delete라는 항목을 만들 것이다.
그대로 두어도 되지만,
이 항목도 저번처럼 외부 파일로 분리하여 Control컴포넌트로 만들었다.
세 항목 중에 하나를 클릭했을 때, 이벤트가 발생하도록 만들어야 하므로,
Control컴포넌트에 onChangeMode 함수를 만들어주고,
Controls.js에서는 onClick에서 함수를 호출해준다.
App.js에서 Control컴포넌트를 추가할 때에는,
받아온 mode를 state의 mode에 넣어준다.
Control.js에서는 mode로 각 각
'create'
'update'
'delete'를 넘겨준다.
3. create 구현 : mode 전환 기능
이제 누르는 것에 따라 Content컴포넌트를 다르게 ReadContent, CreateContent 등으로 분류를 할 것이다.
먼저 그냥 Content를 ReadContent로 이름을 바꾸어 주고,
다른 것도 모두 알맞게 바꾸어 주었다.
누르는 것에 따라 컴포넌트 전체가 모두 변화되어야 하므로,
컴포넌트 삽입부분을 변수로 처리하였다.
render부분에서 _article변수를 만들어 <ReadContent>를 넣어주고, return 부분에 {_article}을 삽입해주었다.
render에 조건문을 추가하여, mode가 'create'일 때에도 추가해준다.
4. create 구현 : form
다음과 같이 form을 만들어준다.
e.preventDefault()는 submit버튼을 눌렀을 때 페이지 넘김을 방지하기 위함이다.
5. create 구현 : onSubmit 이벤트
submit버튼을 눌렀을 때, onSubmit이라는 이벤트가 실행될 것인데,
이 때 CreateContent컴포넌트를 가져다 쓰고 있는 App 컴포넌트의 state 중에 contents에 데이터를 추가하려고 한다.
debugger를 통해 보면, e.target은 form 태그 자체를 의미한다.
form에 title과 desc 둘 다 'React'를 입력하고 debugger를 확인해보면 e.target.title.value엔 React가 들어있는 것을 확인할 수 있다.
onSubmit에서는 e.target.title.value와 e.target.desc.value로 값을 전달해준다.
App.js에서 CreateContents컴포넌트를 만들어줄 때에 onSubmit함수를 만들어둔다.
console을 통해 전달받은 _title과 _desc를 확인해보면 제대로 값이 전달되는 것을 확인할 수 있다.
6. create 구현 : contents 변경
이제 받아온 내용들을 기준으로 state에 넣으면 되는데,
그럴려면 이미 존재하는 contents들의 id를 쭈루룩 읽어와야 한다.
하지만 매번 읽어오는 대신에 constructor안에 인자로
this.max_content_id=3;
이라고 저장해두고 내용이 추가될 떄마다 증가시켜주면 된다.
state가 아닌 이유는 ui에 영향을 주지 않을 요소이기 때문에 합리적으로 밖에다 빼주는 것이다.
(불필요한 렌더링을 피하기 위해서)
증가 시켜준 id와 받아온 _title, _desc를 객체로 만들어서
state의 contents에 push해준다.
그리고 반드시 지금의 상태를 리액트에 알려주기 위해
this.setState를 이용해준다.
하지만 이렇게 하면, React의 성능개선에 까다로운 부분이 생기기에 좋은 방법은 아니다.
7. concat 사용하기
var.arr = {1,2};라는 배열이 있다면,
데이터를 배열에 추가해주는 방법은 두가지가 있다.
arr.push(3);
arr.concat(3);
push는 원본을 바꾼다.
하지만 concat은 원본은 변경하지 않고 새로운 배열이 리턴되기때문에 기존 원본은 지킬 수 있다.
8. crete 구현 : shouldComponentUpdate
위 처럼 코드를 짠다면,
부모 컴포넌트의 state가 바뀌면 TOC와 직접적인 연관이 없는 state가 바뀌어도, 자식 컴포넌트인 TOC가 새롭게 render된다.
작은 프로그램이면 상관없지만, 큰 프로그램이면 굉장히 비효율적일 수 있다.
render를 할 지 하지 말지를 결정하는 기능을 추가할 수 있는데,
이것이 바로 shouldComponentUpdate함수이다.
이 shouldComponentUpdate는 세가지 특징이 있다.
-shouldComponentUpdate 다음에는 render함수가 호출된다
-shouldComponentUpdate의 리턴값이 true이면 render함수가 호출되고, false이면 되지 않는다
-shouldComponentUpdate에서는 바뀐 props와 이전 props에 접근 가능하다
data라는 props만 바뀔 때만 render를 호출되게 한다면 너무 좋을 것이다.
그러므로 아래처럼 코드를 바꾸면 된다.
그렇다면 create를 통해 데이터를 추가했을 때만 TOC의 render가 호출된다.
하지만 문제는 concat으로 하지 않고,
push방식으로 하면 기존의 contents의 원본을 바꾸기 때문에 바꾸기 전의 값과 바꾼 후의 값은 같게 된다.
그러므로 concat을 사용해야지만, 효율적으로 코드를 짤 수 있다.
9. create 구현 : immutable
concat을 사용하면 데이터는 불변성을 가진다.
만약 push를 사용하고 싶다면 위와 같이 Array.from(복사하고픈 배열)을 사용하면 된다.
이 때, 원본 a와 복사한 b는 완전히 다른 개체이다.
이 Array.from을 사용하면, 불필요한 render호출도 막을 수 있다.(8번)
배열의 경우 위와 같이 하면 되는데,
객체의 경우엔 아래와 같이 하면 된다.
첫번째 인자로는 새롭게 추가할 데이터를 넣어주면 된다. 아무것도 추가하고 싶지 않다면 {}로 값을 주어도 된다.
검색할 때에는 immutable.js를 이용하여 찾아보면 된다.
[Reference]
생활코딩 React
'Web > React' 카테고리의 다른 글
npm : 'npm' 용어가 cmdlet, 함수, 스크립트 파일 또는 실행.....악 (0) | 2020.04.23 |
---|---|
10] React Update & Delete (0) | 2020.04.23 |
8] React Event 처리 (0) | 2020.04.23 |
7] React State (0) | 2020.04.23 |
6.5] React Props (default props) (0) | 2020.02.29 |