ref

현재까지는 state를 바꾸면 React가 알아서 화면을 변경해줬다. 그래서 우리가 직접 DOM을 참조할 필요가 없었지만 만약에 input에 focus를 주고 싶은 경우에는 어떻게 할까?

 

기존 바닐라에서는 아래와 같이 하면 됐다.

document.querySelector("input").focus();

하지만 React에서는 대부분 document.querySelector를 사용하지 않는다.

React가 화면을 컨트롤 할 수 있게 해주는 것이 중요하다. 

최대한 React가 제공해주는 것을 사용하자. 이때는 ref를 사용하면 된다.

 

input;

return (
...
<input ref={(c)=>{this.input = c;}} type="number" />
...
)

input을 선언하고, jsx에서 ref={(c) => {this.input = c; }}

 

input을 사용할 때는 js 부분에서 아래와 같이 사용 가능.

 

this.input.focus();

>>>> 따로 메서드로 빼면 아래와 같이 간편해진다.

onRefInput = (c) => {this.input = c;}

return (
	...
	<input ref={this.onRefInput} type="number" />
    ...
);

 

 

state를 변경했을 때 일어나는 일

setState를 할 때 reder()함수가 재호출되면서 리렌더가 일어난다.

해당 개념이 중요한 이유는 나중에 렌더를 너무 많이 하면 느려진다. render에 10초 걸리는 작업이 있다고 하면 state를 변경할 떄마다 10초씩 걸린다고 생각하면 된다.

 jsx부분의 onChange, onSubmit, ref 이런 부분도 모두 render()함수 위의 js 부분에 선언하는 것이 좋은 이유이다. 만약에 jsx 부분에 inline으로 onChange, onSubmit과 같은 함수를 작성해버리면 state를 변경할 때마다 똑같은 함수가 계속 생기게 된다. (state를 변경하면 render()가 재호출되기 때문)

함수형 setState

setState에 함수를 넣고 그 안에서 새로운 state를 리턴을 하는 것.

함수형 setState 구조

this.setState((prevState)=>{
	return {
    	first: Math.ceil(Math.random() * 9),
        second: Math.ceil(Math.random() * 9),
        value:'',
        result : '정답',
        prevAns : prevState.value,
	}
});

함수형 setState와 기존 setState의 차이점

예전 state값을 다음 state 값에 활용 가능.

기존 state 바꾸는 방식으로 하면 비동기 문제가 생긴다.

this.setState({
    value: this.state.value + 1,
});
this.setState({
    value: this.state.value + 1,
});
this.setState({
    value: this.state.value + 1,
});

이렇게 setState를 3번 호출 하면 this.state.value에 +3이 된 값이 들어있어야 하는데, setState가 비동기라 바로 적용되지 않아서 +1만 되는 경우가 생길 가능성이 크다. 

그렇기 때문에 setState를 할 때는 그냥 함수형으로 사용하자. (특히, 기존 state값을 활용할 경우에는 꼭)

Fragment

React에서 화면을 최종적으로 반환할 때는 딱 하나의 태그만 반환해야한다. (부모 태그가 1개여야한다는 것)

그래서 쓸데없는 <div></div> 로 감싸줘야하는데 이것이 css를 적용할 때 방해가 될 때가 많다.

 

그럴 때 사용하는 것이 빈 껍데기 태그인 <></> Fragment를 사용하는 것이 좋다. 

(이것이 에러나면 <React.Fragment></ React.Fragment>로 감싸주면 된다.)

return (
	<React.Fragment>
    	~
	</React.Fragment>
);

 

클래스 컴포넌트에서 주의점

함수 메서드를 따로 만들어서 이벤트 리스너와 연결시킬 때는 화살표 함수를 사용해라. function을 사용하면 this가 달라져서 작동하지 않는다. 

실무에서는 constructor를 사용하지않고 바로 state= {..} 이렇게 선언한다.

class GuGuDan extends React.Component{
            state = {
                first: Math.ceil(Math.random() * 9),
                second: Math.ceil(Math.random() * 9),
                value:'',
                result : '',
            }

            onChangeInput = (e) => {
                this.setState({value: e.target.value});
                console.log(this.state)
            };

            onSubmit = e => {
                e.preventDefault();
                const ans = this.state.first * this.state.second;
                if(ans === parseInt(this.state.value)){
                    this.setState({
                        first: Math.ceil(Math.random() * 9),
                        second: Math.ceil(Math.random() * 9),
                        value:'',
                        result : '정답',
                    })
                }else{
                    this.setState({
                        value:'',
                        result : '땡',
                    });
                }
            }

            render() {
                return (
                    <React.Fragment>
                        <div>{this.state.first} 곱하기 {this.state.second}는?</div>
                        <form onSubmit={this.onSubmit}>
                            <input type="number" value={this.state.value} onChange={this.onChangeInput}/>
                            <button>입력!</button>
                        </form>
                        <div>{this.state.result}</div>
                    </React.Fragment>
                );
            }
        }

 

+ Recent posts