REACT 6일차 (리액트 컴포넌트-3)
Component 클래스는 프로퍼티,state와 생명주기 함수가 들어있는 컴포넌트를 만들 때 사용
PureComponent 클래스는 Component 클래스를 상속받은 클래스다.
PureComponent로 선언한 컴포넌트는 shouldComponentUpdate() 함수에서 shallowEqual()
함수로 얕은 비교를 하여 데이터의 변경이 있으면 화면을 새로 출력하고
Component클래스로 선언한 컴포넌트는 항상 새로 출력한다.
*shallwEqual는 얕은 비교로 같은 요소를 가지면 같다고 본다.
*"==="이나 "=="은 요소가 같아도 새롭게 정의된 배열이면 false로 취급한다.
-----------------------------------------------------------------
함수형 컴포넌트: state가 없는 함수형 컴포넌트
함수형 컴포넌트에는 클래스 선언이 없습니다.
상위 컴포넌트로부터 전달받은 프로퍼티와 컨텍스트만을 이용하여 화면을 구성
함수형 컴포넌트는 state와 생명주기 함수를 사용할 수 없다.
function SFC(props, context){
const { somePropValue } = props;
const { someContextValue } = context;
return <h1>Hello, {somePropValue}</h1>;
}
--------------------------------------------------------------
배열 컴포넌트
자바스크립트는 여러 자료형을 섞어 배열을 만들 수 있다.
이는 XML과 JSX도 배열에 저장할 수 있다는 것이다.
const C_List=[<MyComponent />,<MySecondComponent />,<b>Hi</b>]
위와 같이 배열을 사용하면 map()함수를 통해 여러 화면을 출력할 수 있다.
ex) 유튜브 영상 목록
const T_List = [
{taskName: '과제하기', finished: false},
{taskName: '공부하기', finished: true },
];
const todos=T_List.map(todo=><div>{todo.taskName}</div>);
위와 같이 map을 사용해 배열의 데이터를 바로 JSX로 변경할 수 있다.
배열 컴포넌트의 경우 배열 요소의 개수만큼 반복하므로 성능에 영향을 많이 준다.
따라서 배열 컴포넌트에는 키값을 key로 꼭 정의헤줘야 한다.
const todos=T_List.map(todo=><div key={`tl_${i}`}>{todo.taskName}</div>);
위와 같이 표현할 수 있다.
하지만 filter 함수를 추가하여 배열 항목에서 finished의 값이 false인
항목을 제외하는 등 변형을 하는 경우 인덱스 번호를 키로 사용한다면
키값이 함께 변경되는 문제가 생긴다.
따라서 키값을 고유한 배열 항목을 사용하여 키값의 충돌을 막을 수 있다.
const todos=T_List.map(todo=><div key={todo.taskName}>{todo.taskName}</div>);
---------------------------------------------------------------------
render() 함수에서 여러개의 JSX노드 반환하기
render함수에서 값을 반환할때 여러 컴포넌트만을 반환하면 에러가 생긴다.
render함수는 트리 구조의 노드를 반환해야하기 때문이다.
따라서 <div>로 묶든 의미없는 노드를 추가해야 했다.
하지만 react 16.3버전 이후 개선되어 React.Fragment 컴포넌트가 추가됐다.
<React.Fragment> //혹은 <>,</> 태그를 사용해도 된다.
<Componen />
<TodaysPlan children="123" />
</React.Fragment>
-----------------------------------------------------------------------
컴포넌트에서 콜백 함수와 이벤트 처리하기
콜백 함수란 정의된 위치에서 실행되지 않고 이후 특정 상황에서 실행되는 함수
하위 컴포넌트에서 프로퍼티를 변경해야 할 때 콜백 함수를 프로퍼티로 전달하면 된다.
예를 들어 하위 컴포넌트의 count를 변경하고 싶을 경우
상위 컴포넌트에 아래와 같은 함수를 추가한다.
increaseCount(){
this.setState(({count}) => ({count:count+1}));
}
이렇게 하면 App 컴포넌트의 count값을 변경할 수 있지만
다른 컴포넌트의 값을 변경할 수는 없다.
하지만 increaseCount함수를 프로퍼티로 추가하면 가능하다.
ex) <Counter= count={this.state.count} onAdd={this.increaseCount} />
이렇게만 하면 또 에러가 발생한다.
이유는 this.increaseCount의 this.setstate(...)가 상위 컴포넌트에 있기 때문이다.
위 문제는 bind() 함수로 해결할 수 있다.
ex) <Counter= count={this.state.count} onAdd={this.increaseCount.bind(this)} />
이렇게 하면 호출되는 this의 범위가 상위 컴포넌트에 묶여서 괜찮다.
-----------------------------------------------------------------
컴포넌트에서 DOM 객체 함수 사용하기
컴포넌트에서 window.addEventListener() 함수같은 DOM 객체 함수를 사용하려면
DOM 객체를 컴포넌트 변수에 할당해야 한다. 이떄 특수 프로퍼티 ref를 사용한다.
ref 프로퍼티는 document.getElementById()가 반환하는 객체를 반환한다.
또한 DOM 객체 함수가 필요한 엘리먼트에 콜백 함수 형태로 전달된다.
ex) 스크롤 만들기
export default class ScrollSpy extends React.PureComponent {
constructor(props) {
super(props);
this.setRef = this.setRef.bind(this);
this.checkPosition = this.checkPosition.bind(this);
window.addEventListener("scroll", this.checkPosition);
}
setRef(ref) {
this.ref = ref;
}
checkPosition() {
if (this.ref.getBoundingClientRect().top < window.innerHeight) {
console.log("enter");
} else {
console.log("exit");
}
}
componentDidMount() {
this.checkPosition();
}
componentWillUnmount() {
window.removeEventListener("scroll", this.checkPosition);
}
render() {
return <div ref={this.setRef} />;
}
}
위 코드는 페이스북에서 스크롤을 내릴때 자동으로 다
음 페이지 목록을
추가할 떄 사용한다. 화면스크롤이 변화할 때마다 객체 함수의 위치를 읽어
현재 위치가 화면 안팎인지 측정한다. console.log('enter')이 뜰때마다
다음 페이지 목록을 추가하는 코드를 구현하면 완성이다.