
리액트는 레고처럼 블럭들을 조립하는 방식으로 구성된다. 레고블럭이 콤포넌트에 해당하며 함수형 또는 클래스형으로 정의할 수 있으며 style-component 라이브러리로 css free한 컴포넌트 작성방법도 제공한다.
// 함수형 정의
function App() {
return (
<div className="App">
<p> Hello World!</p>
</div>
);
}
const App = () => {
return (
<div className="App">
<p> Hello World!</p>
</div>
);
}
// typescript로 함수형 정의
const App: React.FC<MyProps> = ({title}) => {
// ...
}
// 클래스형 정의
class App extends Component {
render() {
return <div className="App">
<p> Hello World!</p>
</div>
}
}
모든 콤포넌트의 라이프사이클에 해당하는 mount, update, unmount 이벤트가 있다.
mount시에는 다음의 순서로 호출된다.
constructor() -> render() -> componentDidMount()
update시에는 다음의 순서로 호출다.
render() -> componentDidUpdate()
unmount시에는 componentDidUnmount()가 호출된다.
필요에 따라 해당 이벤트를 오버라이드하여 사용 가능하다.
콤포넌트에 속성을 지정하고자 할때 속성을 전달하는 방식을 정의한다.
먼저 interface 키워드로 Props명세를 정의한다.
interface ContainerProps{
bgColor: string;
}
function component에서는 props: ContainerProps 또는 { 인자들 }: ContainerProps 형태로 사용한다.
const Circle = ({ bgColor }: ContainerProps) => {
return <Container bgColor={bgColor}/>;
}
const Circle = (props: ContainerProps) => {
return <Container bgColor={props.bgColor}/>;
}
필수인자 뿐 아니라 옵셔널 인자도 설정이 가능하다.
interface CircleProps{
bgColor: string;
borderColor?: string;
text?: string;
};
변수명 뒤에 ?를 기입하면 되고 그러면 태그로 사용 시 값을 지정하지 않아도 되며 지정하지 않았을 때는 디폴트값이 적용되어야 하는데 이는 ?? 키워드를 이용하여 설정이 가능하다.
const Circle = (props: CircleProps) => {
return <Container bgColor={props.bgColor} borderColor={props.borderColor ?? "blue"}>{props.text ?? "default text"}</Container>;
}
함수인자를 아래와 같이 구성하면 옵셔널을 더 쉽게 정의할 수 있다.
const Circle = ({ bgColor, borderColor, text="default text"}: CircleProps) => {
return <Container bgColor={bgColor} borderColor={borderColor ?? bgColor}>{text}</Container>;
}
styled-component에서는 <ContainerProps> 형식으로 전달하고 props.{속성이름}으로 접근하여 사용한다.
const Container = styled.div<ContainerProps>`
background-color: ${(props) => props.bgColor};
`;
const Container = styled.div<{bgColor: string}>`
background-color: ${(props) => props.bgColor};
`;
콤포넌트를 작성할때 이벤트를 새로 정의하고자 한다면 먼저 interface를 정의한다.
닫기 아이콘을 콤포넌트로 만든다고 할때 닫기 이벤트를 먼저 정의한다.
interface CloseBtnProps {
onClose: () => void;
}
콤포넌트를 정의할때 타입을 정의한 interface로 한다.
const CloseIcon: React.FC<CloseBtnProps> = ({ onClose }) => {
return <Close onClick={() => { onClose(); }}>
<IoCloseCircleOutline
style={{
width: "20px",
height: "20px",
color: "white",
}} />
</Close>;
}
const CloseIcon: React.FC<CloseBtnProps> 부분이 중요한데 타입을 이렇게 지정하지 않으면 이벤트를 전달할 수 없다.
이렇게 정의된 콤포넌트는 다음과 같이 사용 가능하다.
<CloseIcon onClose={() => {
// 닫기 이벤트 처리 부분.
}} />
state는 콤포넌트에서 사용할 수 있는 값이 유지되는 변수로 이해하면 된다.
const나 let으로 선언한 일반 변수와 다른점은 이 값이 변하면 해당 변수를 사용하는 콤포넌트들 재랜더링된다. 따라서 콤포넌트에서 변경이 되어야 하는 변수들을 다룬다.
useState를 임포트
import { useState } from 'react';
useState 선언
const [state, setState] = useState(초기값(생략 가능));
const plus = () => {
setCount(count + 1);
setCount(count + 2);
setCount(count + 3);
}
** 카운트가 6이 증가해야 할것 같지만 setCount가 누적이 되지 않고 마지막 호출만 처리되면서 3만 증가하게 된다. 주의해야 할 사항이다.
const plus = () => {
setCount(count => count + 1);
setCount(count => count + 2);
setCount(count => count + 3);
}
** 안전하게 현재값을 넘겨받는 형식을 주로 사용하길 바란다.
어떤 값의 상태가 변할 때 마다 특정 함수가 호출되도록 해주는 훅이다.
useEffect(함수, [변수목록])
const [todos, setTodos] = useState([]);
useEffect(() => {
localStorage.setItem("todos", JSON.stringify(todos));
}, [todos]);
todos의 내용이 변경될 때마다 localStorage에 값을 저장하는 예이다.
useEffect의 두번째 인자에 빈 배열을 추가하면 콤포넌트가 처음 렌더링될때만 함수가 호출된다. 이후 렌더링이 다시 발생할때는 무시된다. 함수형 콤포넌트의 생성자 역할을 하게 된다.
const MyComp = () => {
useEffect(() => {
console.log("한번만 호출됨");
}, []);
console.log("렌더링될때마다 호출됨");
return <></>;
}
콤포넌트의 css styling을 편하게 하기 위해 고안되었다.
Theme나 Props로 스타일을 간편하게 관리가 가능하다. 그리고 콤포넌트별로 스타일을 관리할 수 있다.
프로젝트에 추가하려면 다음 명령을 실행한다.
npm install --save styled-components
다음 형식으로 기존 태그를 새로운 태그로 정의할 수 있다.
const NewComponent = styled.[태그명]
다음은 div를 새로 Father라는 콤포넌트로 정의한 예이다.
const Father = styled.div`
display: flex;
`
function App() {
return <Father></Father>
}
Props로 프로퍼티를 넘겨서 해당 콤포넌트의 스타일을 변경할 수 있다.
const Box = styled.div<{bgColor: string}> `
background-color: ${(props) => props.bgColor};
width: 100px;
height: 100px;
`
function App() {
return <Father>
<Box bgColor="tomato" />
<Box bgColor="wheat" />;
</Father>
}
상속을 통해 부모 콤포넌트의 속성을 내려 받을 수 있다.
const Circle = styled.Box `
border-radius: 50px;
`
function App() {
return <Father>
<Box bgColor="tomato" />
<Circle bgColor="orange"/>
}
as 키워드를 tag에 사용하여 실제 렌더링 될 때 태그를 변경할 수 있다. 이는 기존 styled component의 css속성들을 그대로 유지하면서 태그만 변경하여 그 태그의 기능을 사용하고 싶을 때 유용하다.
아래는 Box형태를 유지한 채 해당 박스가 a 태그로 동작하게 하는 예이다.
function App() {
return <Father>
<Box bgColor="tomato" />
<Box as="a" href="/" bgColor="orange"/>
}
위코드는 두개의 Box 태그를 사용하였지만 실제 렌더링 될 때 두번째 Box는 스타일을 유지하면서 anchor 태그로 렌더링 되는것을 알 수 있다.
attrs를 styled component 정의시 추가하여 디폴트 값을 지정할 수 있다.
const Box = styled.div.attrs({
background-color: tomato;
})`
width: 100px;
height: 100px;
`;
styled component가 하위요소들을 가지고 있을 때 상위 콤포넌트에서 하위요소를 select하여 속성을 변경할 수 있다.
const MainContainer = styled.section`
display:flex;
width:100vw;
`
const Memo = styled.div`
width:300px;
height:500px;
`
const ShadowMemo = styled(Memo)`
box-shadow: 2px 4px 8px;
funtion Section2 () {
return(
<>
<MainContainer>
<Memo>Lorem Ipsum</Memo>
<ShadowMemo>Lorem Ipsum</ShadowMemo>
</MainContainer>
<Memo>Lorem Ipsum</Memo>
</>
)
}
MainContainer안에 Memo와 Memo를 상속한 ShadowMemo가 있다. 여기서 Memo의 background-color만 변경하고자 할때 Memo에서 변경한다면 ShadowMemo도 변경되어버리기 때문에 원하는 동작이 아니게 된다. 이런 경우 MainContainer에서 selector를 통하여 접근하여 변경이 가능하다.
const MainContainer = styled.section`
display:flex;
width:100vw;
${Memo} {
background-color:black;
color: white;
}
`
${콤포넌트명}으로 하위 콤포넌트에 접근하여 다른 속성을 줄 수 있다.
다음은 여러가지 select예제이다.
BtnArea 아래 a 태그들 중에 첫번째만 flex: none;을 적용하고 나머지는 다른 속성을 적용하도록 할 수 있으며 a 태그 내의 span의 스타일을 따로 적용하는 예제이다.
export const BtnArea = styled.div`
display: flex;
flex-wrap: wrap;
margin-top: 1.6rem;
gap: 0.8rem;
a {
width: 100%;
height: 4.8rem;
margin: 0;
border-radius: 0.8rem;
color: #fff;
border: 0.1rem solid #815DFB;
background-color: #815DFB;
display: inherit;
justify-content: center;
align-items: center;
&:first-child {
flex: none;
}
&:not(first-child) {
height: 4rem;
flex: 1;
}
span {
width: 100%;
display: inherit;
justify-content: center;
font: inherit;
}
}
`;
이렇게 div로 감싸진 내부의 태그들을 선택적으로 다른 속성을 부여하고자 할때 다양한 방법으로 적용해줄 수 있다.