React
create 구현 : form
글을 추가하는 기능의 폼 완성
폼을 만들기 전 App.js의 mode를 Create로 바꾼다.-> 디버깅 편하게
< form> < p>< input type="text" name="title" placeholder="title">< /input>< /p> < p>< textarea name="desc" placeholder="description">< /textarea>< /p> < p>< input type="submit">< /input>< /p> < /form>
form에 action 같은 정보 전송 방식을 넣어주고 onSubmit 이벤트 함수를 넣는다.
여기서 e.preventDefault(); 는 원래 submit 버튼을 누르면 action으로 지정된 곳으로 이동하게 되는데
그 액션을 없애고 비동기적으로 페이지를 불러오게 된다. (바뀌는게 아니라 변경된다.)
< form action="/create_process" method="post" onSubmit={function(e){ e.preventDefault(); alert('submit!!!'); }.bind(this)} > //폼은 이렇게
이렇게 하면 경고창이 뜨지만 페이지 전환이 안된다!
다음은 app 컴포넌트 컨텐츠 끝에 사용자가 입력한 정보를 추가시키고
글 목록도 자동으로 바뀌도록 해야한다.
create 구현 : onSubmit 이벤트
submit을 사용자가 클릭했을 때 onSubmit 이벤트가 실행된다.
이때 CreateContent 컴포넌트를 쓰고 있는 App 컴포넌트의 contents 데이터에 데이터를 하나 더 추가하는 방법을 알아보다.
submit 클릭하면 CreateContent로 설치된 함수를 실행한다.
인자로 title과 desc가 전달될 수 있다면
setState를 통해서 새로운 content 값을 추가
그러기 위해서 CreateContent의 onSubmit이라고 하는 props를 호출해야한다.
CreateContents.js 컴포넌트 파일 안에서
props를 호출한다.
debugger; 로 이벤트 찾기
onsumbit 이벤트 가 발생했을 때 form의 각각의 value값을 어떻게 가져올 수 있을까?
e의 target 자체가 form을 가리킨다.
e - target 를 개발자도구로 보면 아-주 아래에 value가 이 form 값을 가져오는 것 볼 수 있다.
그래서 이 title과 desc의 값은
e.target.title.value
e.target.desc.value
로 가져올 수 있다.
이런 사실을 바탕으로 위의 두개를 onsubmit의 인자로 준다.
< form action="/create_process" method="post" onSubmit={function(e){ e.preventDefault(); this.props.onSubmit( e.target.title.value, e.target.desc.value ); }.bind(this)} >
이렇게 되면 title과 desc 값을 얻을 수 있다!!
create 구현 : contents 변경
onsubmit이 발생했을 떄 CreateContent 컴포넌트의 onsubmit의 props가 실행되고 있다.
App 컴포넌트에 contents 끝에 데이터가 추가되도록 하자.
우선 id 값을 1 더 크게 만들어야 한다.
contents:[ {id: 1, title: 'HTML', desc: 'HTML is information...'}, {id: 2, title: 'CSS', desc: 'CSS is design...'}, {id: 3, title: 'Javascript', desc: 'Javascript is interactive...'} ]
class App extends Component { constructor(props){ super(props); this.max_content_id = 3; this.state = { mode: 'create', selected_content_id: 2 , //기본적으로 2번 컨텐트가 선택 subject:{title:'WEB', sub: 'world wide web!'}, welcome:{title:'welcome', desc: 'Hello, React'}, contents:[ {id: 1, title: 'HTML', desc: 'HTML is information...'}, {id: 2, title: 'CSS', desc: 'CSS is design...'}, {id: 3, title: 'Javascript', desc: 'Javascript is interactive...'} ] } }
App 컴포넌트 안에 객체의 값으로 별도 분리한 이유는
max_content_id는 데이터를 push 할 때 id 값을 뭐로 할까 하는 정보일 뿐
ui에 영항을 주지 않기 때문에
state의 값이 되지 않는다.(안에 넣으면 불필요한 렌더링이 발생)
그럼 이제 onSubmit 함수에 위의 값을 넣고 1 증가시킨다.
this.max_content_id = this.max_content_id+1;
그러면
{id:this.max_content_id, title:_title, desc:_desc}
아래와 같은 객체를 생성해서 contents 끝에 추가한다.
setState를 써서 변경한다!!
배열에 값을 추가하는 방법은 두 가지
1) .push
var arr = [1, 2];
arr.push(3);
arr = [1, 2, 3];
push는 원본을 바꾼다.
2) .concat
var arr2 = [1, 2];
arr2.concat(3);
arr2 = [1, 2, 3]
concat은 원본을 바꾸지 않는다.
새로운 배열을 변수에 담아 새 배열을 사용해야 한다.
리액트 state에 값을 추가할 때는 push와 같이 origin data를 건드는 것은 써선 안된다.
새로운 데이터를 추가하는 것을 써야한다.
만약 지금의 경우
this.state.contents.push( {id:this.max_content_id, title:_title, desc:_desc} );
처럼 push 를 사용하면 기존 컨텐츠 배열에 값을 하나 추가하는 것
push를 사용하는 방식은 추후 성능을 개선하기 어렵게 만들기 때문에
var _contents = this.state.contents.concat( {id:this.max_content_id, title:_title, desc:_desc} ) this.setState({ contents: _contents });
과 같이 이용해야 한다.
이 방식은 어떻게 원본 데이터를 바꾸지 않으면서 데이터를 state에 갱신할 것인가 하는 것이다.