본문 바로가기
Language/React

[React] create 구현: form , contents 변경

by 며루치꽃 2020. 12. 23.

form을 제작할 때는 onSubmit 을 호출해야합니다. onSubmit은 submit 버튼을 클릭했을 때, submit 태그를 포함하고 있는 form 태그에 onSubmit 이벤트를 설치해두면, 이벤트가 실행되도록 약속되어 있습니다. 이 것은 html의 form 태그가 가지고 있는 특징입니다. 

 

CreateComponent.js

<form action="/create_process/" method="post"
	onSubmit={function(e){
	e.preventDefault();
	alert('submit');
	}}
>
<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에서 submit을 클릭했을 때, onSubmit 이벤트가 실행이 될 것인데, 이벤트가 실행되었을 때 CreateComponent를 가져다 쓰고 있는 App 컴포넌트의 contents 배열에 추가하는 것을 목표로 해보겠습니다.

 

해야할 것: Submit 버튼이 클릭 되었을 때, CreateContent의 이벤트가 있는 곳에서 이벤트를 실행시켜야 합니다. 

 

<CreateContent onSubmit={function(_title, _desc){ //onSubmit이 주어졌을 때, 이 함수의 입력값으로 title과 desc가 전달될 수 있다면, setState를 통해서 새로운 컨텐트 값을 추가하면 됩니다. 
                // 이 부분이 실행될 때마다 새로운 컨텐츠를 추가하고 싶다
               
}.bind(this)}></CreateContent>

위의 코드와 같이 onSubmit가 발생하였을 때, onSubmit 안에 있는 함수를 실행할 것인데, 이 함수의 입력값으로 title과 desc가 전달될 수 있다면, setState를 통해서 새로운 컨텐트 값을 추가하면 됩니다. 

그걸 하기 위해서 

1) CreateContent 컴포넌트의 onSubmit props를 CreateContent에서 호출합니다.

2) onSubmit 이벤트가 발생하였을 때, 첫 번째 인자로는 title, 두 번째 인자로는 desc를 전달해줘야합니다. 

3) 그렇게 하려면 각각의 form의 value 값을 가져와야하는데 e.target 을 하게되면 이벤트가 발생한 form을 가르키게 되는데 

e.target.조회할변수명.value 를 하게 되면 이벤트 변수의 값을 가져올 수 있습니다. 

4) CreateContent 컴포넌트의 onSubmit 호출될때 App의 onSubmit이 호출될 것입니다. 

 

정리하자면, create 버튼이 실행되었을 때, 

1) CreateContent 컴포넌트의 onSubmit 이벤트가 발생하였을 때, CreateContent의 onSubmit props를 실행하도록 했다. 

2) 그러면 App에 있는 onSubmit이 실행되면서 

3) 속해있는 App 컴포넌트의 contents에 끝에다가 데이터를 추가해야합니다.

Contents 변경

App.js

CreateContent onSubmit={function(_title, _desc){ //onSubmit이 주어졌을 때, 이 함수의 입력값으로 title과 desc가 전달될 수 있다면, setState를 통해서 새로운 컨텐트 값을 추가하면 됩니다. 
                // 이 부분이 실행될 때마다 
                this.max_content_id = this.max_content_id + 1;
                this.state.contents.push(
                    {id:this.max_content_id, title:_title, desc:_desc }
                    );
                this.setState({ // Contents의 값을 바꾸었기 때문에 this.setState로 알려줘야합니다. 
                    contents:this.state.contents
                });
                console.log(_title, _desc);
}.bind(this)}></CreateContent>

데이터를 추가하기 위해서, contents의 id를 읽어서, 기존 id보다 1이 더 큰 id 값을 만듭니다.

기존의 이벤트가 실행될 때마다, 기존 id보다 1이 더 큰 id 값을 만들고, 

id와 title, desc 를 추가하는 객체를 만들어서 App contents의 끝에다가 추가합니다.

그리고 contents의 값을 바꿨기 때문에 push를 이용했기 때문에 setState를 사용하여 바뀐 컨텐츠를 줍니다.

push를 하게 되면, 기존의 데이터 original data인 state.contents 를 바꾸게 되는데 이는 좋지 않은 방법입니다. 

이를 해결하기 위해 기존의 데이터를 바꾸는 방법보다 기존의 데이터는 가만히 보전하고,

concat을 이용해 this.state.contents.concat에 새로운 데이터를 추가하는데 그것의 return 값을 _contents 에 추가하고 

_contents 변수에 setState로 넣어주면 기존이 들어있던 데이터가 새로운 concat으로 만들어진 새로운 데이터로 추가되게 됩니다. 


concat의 이해

push() 함수를 이용하여 배열을 조작하게 되면 기존의 데이터가 바뀌는 모습을 볼 수 있습니다.

 

concat() 함수를 이용하여 배열 a를 출력해보면 기존의 데이터가 변경이 일어나지 않는 모습을 알 수 있습니다,

concat() 은 기존 객체를 바꾸지 않고 기존 객체를 복사하는 것을 알 수 있습니다. 

 

setState에 어떠한 값을 줄 때는, 기존의 값의 원본을 수정하지 않고, 새로운 값을 복사하여 setState에 설정해야 합니다.


현재 TOC 는 글 목록을 가르킵니다. TOC가 화면에 표시되기 위해서는 constructor(생성자)의 contents가 담고 있는 배열들입니다. 배열의 내용이 바뀌었다면, TOC 컴포넌트의 render가 호출되는 것을 통해서, 다시 그려집니다. 

TOC 내용이 바뀌지 않았더라면, render함수가 호출이 되는 것은 화면을 다시 그리는 작업이기 때문에 불필요 합니다. 

성능을 향상 시키고 싶을 때는, render함수가 실행될지, 실행될지 않을지를 개발자가 결정할 수 있도록 React에서는 개발자가 결정할 수 있게 만들어놨습니다. 

 

shouldComponentUpdate(newProps, newState){
        console.log('TOC render shouldComponentUpdate'
            ,newProps.data
            ,this.props.data
        );
        return false
    }

shouldComponentUpdate 

1) shouldComponentUpdate render 이전에 실행이 된다

2) shouldComponentUpdate 값이 true일 경우, render가 호출되고 false일 경우 render가 호출되지 않는다

3) shouldComponentUpdate는 새롭게 바뀐 값과 이전 값의 접근할 수 있다.

첫번째 인자로 인해 바뀐 값을 알 수 있고, 두번째 인자를 통해 현재 값을 알 수 있습니다.

 

TOC로 들어오는 data로 들어오는 props 의 값이 바뀌었을 때 render가 호출되고, 

바뀌지 않았을 때 render가 호출된다면 render 호출횟수를 줄일 수 있습니다. 

댓글