** 참고
리액트가 왜 함수형 컴포넌트를 선택했으며, 리액트 훅이 왜 나온것인지
https://ko.reactjs.org/docs/hooks-intro.html#motivation
함수형 컴포넌트
import React, {useState} from 'react';
import Styled from 'styled-components/native';
import Button from '~/Components/Button';
const Container = Styled.SafeAreaView`
flex: 1;
`;
const TitleContainer = Styled.View`
flex: 1;
justify-content: center;
align-items: center;
`;
const TitleLabel = Styled.Text`
font-size: 24px;
`;
const CounterContainer = Styled.View`
flex: 2;
justify-content: center;
align-items: center;
`;
const CountLabel = Styled.Text`
font-size: 24px;
font-weight: bold;
`;
const ButtonContainer = Styled.View`
flex: 1;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-around;
`;
interface Props {
title?: string;
initValue: number;
}
const index = ({title, initValue}: Props) => {
const [count, setCount] = useState<number>(initValue);
return (
<Container>
{title && (
<TitleContainer>
<TitleLabel>{title}</TitleLabel>
</TitleContainer>
)}
<CounterContainer>
<CountLabel>{initValue + count}</CountLabel>
</CounterContainer>
<ButtonContainer>
<Button iconName="plus" onPress={() => setCount(count + 1)} />
<Button
iconName="minus"
onPress={() => setCount(count > 0 ? count - 1 : count)}
/>
</ButtonContainer>
</Container>
);
};
export default index;
클래스 컴포넌트
...
interface Props {
title?: string;
initValue: number;
}
/**
* 클래스 컴포넌트에서 State를 사용하는 경우, 함수형 컴포넌트와는 다르게
* State의 타입을 미리 정의하고 컴포넌트 선언 시 해당 타입을 지정한다.
*/
interface State {
count: number;
error: Boolean;
}
class Counter extends React.Component<Props, State> {
constructor(props: Props) {
/**
* 생성자 함수에서는 항상 super(props);를 사용하여
* 부모 컴포넌트(React.Component)의 생성자 함수를 호출해야 한다는 점이다.
*/
super(props);
console.log('constructor');
/**
* 함수형 컴포넌트에서는 useState로 State를 생성할 때, 초기값을 지정했으나
* 클래스 컴포넌트에서는 생성자에서 State의 초기값을 지정한다.
*/
this.state = {
count: props.initValue,
error: false,
};
}
render() {
/**
* 클래스 컴포넌트에서는 함수형 컴포넌트와는 다르게
* Props와 State에 접근하기 위해서 this를 함께 사용한다.
*/
const {title} = this.props;
const {count, error} = this.state;
return (
<Container>
{!error && (
<>
{title && (
<TitleContainer>
<TitleLabel>{title}</TitleLabel>
</TitleContainer>
)}
<CounterContainer>
<CountLabel>{count}</CountLabel>
</CounterContainer>
<ButtonContainer>
<Button
iconName="plus"
/**
* State는 불변값이므로 변경하고자 할 때는
* this.setState 함수를 사용하여 State 값을 변경한다.
*/
onPress={() => this.setState({count: count + 1})}
/>
<Button
iconName="minus"
onPress={() =>
this.setState({count: count > 0 ? count - 1 : count})
}
/>
</ButtonContainer>
</>
)}
</Container>
);
}
/**
* 클래스 컴포넌트는 함수형 컴포넌트와 다르게 라이프 사이클 함수들을 가지고 있다.
*/
static getDerivedStateFromProps(nextProps: Props, prevState: State) {
console.log('getDerivedStateFromProps');
return null;
}
componentDidMount() {
console.log('componentDidMount');
}
getSnapshotBeforeUpdate(prevProps: Props, prevState: State) {
console.log('getSnapshotBeforeUpdate');
return {
testData: true,
};
}
componentDidUpdate(prevProps: Props, prevState: State, snapshot: ISnapshot) {
console.log('componentDidUpdate');
}
shouldComponentUpdate(nextProps: Props, nextState: State) {
console.log('shouldComponentUpdate');
return true;
}
componentWillUnmount() {
console.log('componentWillUnmount');
}
componentDidCatch(error: Error, info: React.ErrorInfo) {
this.state({
error: true,
});
}
}
export default Counter;
'javascript > react.js' 카테고리의 다른 글
[React_Native] References (0) | 2020.06.16 |
---|---|
[React_Native] AsyncStorage 사용법 (0) | 2020.06.15 |
[React-Native] 프로젝트 준비 - App 생성 가이드라인 (0) | 2020.06.13 |