베이스 캠프
헷갈리는 개념이 있을 때 이미지 검색을 해보자.
인포그라피를 확인한다.
props are read-only (바꾸는 것 금지)
states can be modified using this.setState (내부적으로 필요한 것은 state로 관리한다)
props와 states 모두 render()함수 호출한다.
두 가지를 적절히 사용하면서 UI를 바꿀 수 있다.
사용자의 props,
구현자의 states
상위 컴포넌트가 하위 컴포넌트로 값을 전달할 때는 props로 전달한다.
하위 컴포넌트가 상위 컴포넌트로 값을 바꾸고 싶을 때는 event를 통해서 한다.
vs.
REDUX는 하나의 저장소이므로
값이 하나 바뀌면 전체가 알아서 바뀐다.
소개
Create
Read
Update
Delete
중 먼저 Create 공부한다.
하려는 것 : 목차와 본문 사이에 생성, 수정, 삭제 버튼을 만든다.
create 버튼을 누르면 App 컴포넌트의 mode: "create"로 바뀐다.
Content 컴포넌트가 글 추가 컴포넌트로 바뀐다.(form, input, submit 이 들어있다.)
form 에 내용 넣고 저장하면, App 컴포넌트에 state의 contents의 목록에 새로운 정보(id, title, desc)가 객체로 담겨서 추가 된다.
TOC에 표시될 내용들이 늘어난다.
mode 변경 기능
[create, delete, update 버튼 만든다]
TOC 와 Content 컴포넌트 사이에 <ul>태그 만든다. 그 안에
create, update 링크를 만든다.
delete 는 버튼과 같은 operation 개념의 기능을 쓴다.
Cotrol 컴포넌트를 파일로 만들어 ul 내용을 잘라내 붙여 따로 저장한다.
Control.js 파일에서 return( ); 안에 <ul>내용을 넣는다.
App.js 파일에서 Cotrol을 연결한다.
App.js 파일에서 return 부분에 <Control></Control>컴포넌트 넣는다.
이 안에 이벤트 핸들러를 넣는다.
create, delete, update 버튼 클릭했을 때, onChangeHandler가 실행되게 만든다.
onClick 함수 사용한다.
e (event)를 받는다.
this.props.onChangeMode("create"); 실행했을 때의 모드가 "create"라고 알려준다.
update, delete <li>태그 안에도 복붙해서 넣는다. 단, "update", "delete"라고 바꾼다.
App.js에서 onChangeMode가 호출될때, _mode라는 값으로 첫번째 인자를 받는다.
mode라는 변수로 현재 상태가 전달된다.
그때마다 App 컴포넌트 state의 mode: 값을 바꾼다.
결론 : 현재 상태에 따라서 mode 값이 바뀐다.
mode 전환 기능
[ App.js의 mode: create 이면 Content가 create_content라는 컴포넌트로 바꾸게 한다.
App.js의 mode: read 이면 Content가 read_content라는 컴포넌트로 바꾸게 한다. ]
ReadCreate.js 만들고
기존 <Content></Content>컴포넌트의 이름을 모~두 ReadContent로 바꾼다.
이렇게 바뀌면 성공한 것이다.
CreateContent.js 만들고, 본문영역 <article></article>안에 제목과 <form> 태그를 넣는다.
[클릭하면 ReadContent 컴포넌트 부분을 CreateContent 컴포넌트로 바꾼다]
ReadContent 부분이 가변적으로 바뀌게 하기 위해서 {_article} 변수로 처리한다.
바뀌는 부분인 render()에서 변수를 설정한다.
if 일 때도, else if 일 때도 _article 변수는 존재한다.
[mode: create 일때는 CreateContent 화면에 출력하게 한다.]
else if 를 추가해서, 코드를 넣는다.
결과 : 브라우저 화면에서 create 클릭하면 콘솔 컴포넌트에서 ReadContent가 CreateContent로 바뀐다.
브라우저 본문 부분에 Create라는 제목도 잘 출력된다.
form 만들기
CreateContent.js 에서 form 태그 넣어준다. (입력, 텍스트창, 제출)
App.js 에서 mode: create로 바꿔준다.
기본이 create이기 때문에 브라우저에서 form 기능이 뜬다.
브라우저 결과 화면
html의 form 기능인 제출 이벤트를 만든다. onSubmit={ }
e.preventDefault(); 페이지 전환이 안 된다.
form이 제출되었을 때 경고창을 통해서 'Submit!!'이라는 알림이 뜨게한다.
onSubmit 이벤트
하려는 것 : CreateContent.js에서
사용자가 submit버튼을 클릭했을 때 onSubmit이벤트가 실행된다.
그러면 CreateContent를 가져다 쓰고 있는 App컴포넌트의 contents라는데이터 끝에 데이터를 추가한다.
[submit버튼을 클릭했을 때, CreateContent함수를 실행시킨다.]
onSubmit 함수를 만든다.
인자로 _title, _desc 전달한다.
함수 내용으로는 새로운 컨텐츠값을 넣는다.
onSubmit라는 props를 호출한다.
CreateContent.js에서
onSubmit 함수 안에 this.props.onSubmit(); 라고 입력한다.
this.props.onSubmit();안에 e.target.title.value와 desc를 넣는다.
이것은 함수의 인자인 e의 target인 onSubmit 함수의 title/desc의 값을 출력한다.
이 얻은 값을 App.js에서
onSubmit 함수 안에서 사용한다.
contents 변경
[App 컴포넌트의 contents에 끝에 데이터 추가해야 한다.]
기존의 contents의 id값을 쭉 읽어서 그보다 1 더 큰 값을 알아야 한다.
this.max_content_id = 3; 숫자는 마지막 id와 같아야 한다.
this.state 처럼 state를 할 필요가 없다. 불필요한 렌더링이 생긴다.
render에서
onSubmit 함수 안에서
this.max_content_id = this.max_content_id + 1
이렇게 1씩 증가시킨다.
{id:this.max_content_id, title:_title, desc:_desc}
객체를 생성해서 contents 끝에 추가한다.
this.state.contents.push(); 안에 넣는다.
그리고 setState를 설정한다.
결과 : 브라우저 화면에서 form에 입력한 값이 목록에 추가되어서 나온다. 콘솔에서 확인해도 아이디값이 4인 목록이 추가가 된다.
그러나 이것은 좋지 않은 방법이다. 리액트의 성능을 개선하려 할 때 불편하다.
#push : 원래 배열의 값이 바뀐다.
var arr = [1, 2];
arr. push(3);
(arr 출력) [1, 2, 3]
#concat : 원본을 변경한 새로운 배열이 생긴다.
var arr2 = [1, 2];
var result = arr2. concat(3);
(result 출력) [1, 2, 3]
state에 값을 추가할 때는 push를 쓰지 않는다. concat을 쓴다. (새로운 데이터를 추가하는 것을 쓴다.)
_contents 라는 변수에 넣고, 그 변수를 setState의 content의 값으로 쓴다.
(기존의 setState의 값이 새로만든 값으로 교체된다.)
shouldComponentUpdate (추가 공부)
문제점 : 왜 concat이 필요한가? (왜 push는 비추인가?)
App 컴포넌트의 contents가 바뀌지 않았다면, 글목록을 표시하는 TOC컴포넌트의 render는 호출되는 것이 안 좋다.
그런데! 관계없는 (예) create를 클릭해도 TOC컴포넌틔 render는 호출된다. 불합리하다. 프로그램이 커지면 문제가 된다.
shouldComponentUpdate()함수
컴포넌트의 render함수가 실행될지 않을지를 개발자가 결정하게 하는 함수다.
render 이전에 실행된다.
이전 : 부모 컴포넌트가 바뀌면 자식 컴포넌트가 모두 render 호출되었다.
이후 : shouldComponentUpdate를 사용하고 무조건 false로 return하면, render함수는 호출되지 않는다. submit해서 데이터를 추가해도 반영되지 않는다.
즉, true이면 render 호출되고, false이면 render 호출되지 않는다.
함수의 매개변수
newProps : 해당 컴포넌트의 props가 바뀌었을 때, 그 바뀐 값
newState : 해당 컴포넌트의 state가 바뀌었을 때, 그 바뀐 값
newProps.data VS this.props.data : 새롭게 바뀐값과 이전값에 접근할 수 있다.
하고싶은 것 : TOC에 들어오는 _contents라는 데이터가 바뀌면 render호출, 안 바뀌면 render호출 안 되게 하고 싶다.
결론 : push를 사용해서 원본이 바뀌지 않으면 이전값과 현재 값이 같아져 버린다... concat을 사용해라.
immutable(불변성) (추가 공부)
원본을 바꾸지 않는다.
#Array.from : 새로운 배열을 만든다.
var a = [1, 2];
var b = Array.from(a);
console.log(a, b, a===b);
(출력)
(2)[1, 2] (2)[1, 2] false
a와 b는 내용이 같을 뿐 완전히 다른 배열이다.
var a = [1, 2];
var b = Array.from(a);
b.push(3);
console.log(a, b, a===b);
(출력)
(2)[1, 2] (3)[1, 2, 3] false
concat을 쓰면 모든 연산에 대해서 불변인지, 가변인지 따져봐야되서 힘들다.
Array.from을 사용하면 push를 하던, concat을 하던 상관이 없다.
newContents라는 변수에 입력하고,
그 변수에 push를 한다.
그리고 setState의 값을 newContent로 바꾼다.
결과 : 브라우저에서create로 데이터 추가하면 잘 되고, 다른 목록을 클릭해도 console에서 render함수는 호출되지 않는다.
#Object.assign() : 새로운 객체를 만들 때 사용한다.
var a = {name : 'sigcho' };
var b = Object.assign({ }, a); //첫번째 인자에는 아무것도 주지 않는다.
console.log(a, b, a===b);
(결과)
{name: 'sigcho'} {name: 'sigcho'} false
a와 b는 내용이 같을 뿐 완전히 다른 객체이다.
var a = {name : 'sigcho' };
var b = Object.assign({ }, a);
b.name = 'egoing'
console.log(a, b, a===b);
(결과)
{name: 'sigcho'} {name: 'egoing'} false
(추가)
"welcome"의 경우 원본을 교체한 것이다.
concat 역시 원본을 (복제해서) 교체한 것이다.
Array.from ~ push 역시 원본을 교체한 것이다.
어렵다고 생각되면 구글에 immutable.js 검색하기
immutable 장점 : 모든 명령어들이 원본에 대해서 불변하기 때문에 일관된 코드를 사용할 수 있고, 혼란이 적다.
'React' 카테고리의 다른 글
노마드코더 : React(영화 웹 서비스) - 2. 컴포넌트, JSX, Props (0) | 2020.11.26 |
---|---|
생활코딩 : React - Update & Delete 기능 구현 (0) | 2020.11.18 |
생활코딩 : React - 컴포넌트 이벤트 : onChangePage 이벤트 생산자가 되다 (17강) (0) | 2020.11.07 |
생활코딩 : React - 이벤트 : state와 props 그리고 render의 관계, e.preventDefault, bind, setState 함수 (16강) (0) | 2020.11.07 |
생활코딩 : React - State 소개, 사용, key (15강) (0) | 2020.11.06 |