이벤트 변화
무언가를 "기억하게" 만들어 "뭔가 (X)"를 표시하려 한다.
이때 component는 state를 사용하게 된다
Square클릭할 때, 호출할 함수생성 (Board.js)
handleClick(i) {
const square = this.state.squares.slice(); // slice로 통째 복사
squares[i] = 'X';
this.setState({squares: squares});
}
Array.prototype.slice()
어떤 배열의 begin부터 end까지 (end미포함)에 대한 얕은 복사본을 새로운 배열객체로 반환.
원본배열은 바뀌지 않는다.
위에서 만든 함수를 props로 Square컴포넌트에 전달 ( Board.js)
<props에 함수도 저장할 수 있다?>
renderSquare(i) {
return <Square
value={this.state.squares[i]}
onClick={() => this.handleClick(i)}
/>
}
내려받은 props를 위한 Square컴포넌트도 변경한다 (Square.js)
render() {
return (
<button className="square" onClick={()=> this.props.onClick()}>
{this.props.value}
</button>
리액트 불변성 지키기
불변성? 값이나 상태를 변경할 수 없는 것을 의미.
자바스크립트 타입을 통해서 알아본다면, <C#이나 java나 동일한?>
- 원시타입 : 불변성 (immutable) - Boolean, String, Number, null, undefined, Symbol
- 참조타입 : mutable - Object, Array
기본적으로 원시타입에 대한 참조 및 값을 저장하기 위해 call stack 메모리 공간 사용.
참조타입은 heap이란 별도 메모리 공간을 사용.
이 경우 개체 및 배열 값이 아닌, heap 메모리 참조 ID를 값으로 저장
원시타입 | - 고정된 크기로 call stack메모리에 저장. 실제 데이터가 변수에 할당 - let name = "John" name = "Smith" name 변수를 Smith로 대체한 것이 아닌 메모리 영역 a에 있는 John을 그대로 두고, 메모리 영역 b에 Smith를 새로 할당한 것 (불변성을 위해서 따로 신경써주지 않아도 된다) |
참조타입 | - 데이터크기가 정해지지 않고 call stack 메모리에 저장. 데이터값이 heap에 저장되며, 변수에 heap메모리의 주소값이 할당 - let arr = ['a', 'b', 'c'] arr = ['d', 'e', 'f' ] call stack의 참조 ID는 동일하게 유지되고 heap 메모리에서만 변경된다. (불변성이 유지되지 않기에 리액트에서 따로 신경을 써줘야 한다) |
불변성을 지켜야 하는 이유?
- 참조타입에서 객체, 배열의 값이 변할 때 원본 데이터가 변경되기에 이 원본 데이터를 참조하고 있는 다른 객체에서 예상치 못한 오류가 발생할 수 있어서 프로그래밍 복잡도가 상승
- 리액트에서 화면을 업데이트할 때 불변성을 지켜서 값을 이전값과 비교해서 변경된 사항을 확인한 후 업데이트하기에 불변성을 지켜줘야 한다
불변성을 지키는 방법.
- 참조타입에선 값을 바꿨을 때 call stack주소값은 같은데 heap값만 바꿔주기에 불변성을 유지할 수 없으므로 아예 새로운 배열을 반환하는 메서드를 사용한다.
spread operator, map, filter, slice, reduce
- 원본 데이터를 변경하는 메소드 : splice, push