먼저 왼쪽의 목록 컴포넌트부터 만들어보도록 하겠습니다.
목록 컴포넌트가 해주는 일은 간단합니다.
목록 데이터를 받아 그려줍니다. 목록의 메모를 클릭시 클릭된 메모를 오른쪽에 그려줍니다.
이번 예제에서는 Context API 를 이용하여 데이터의 상호작용이 이루어 질 수 있도록 합니다.
먼저 src 폴더 아래에 memos 폴더와 content 폴더를 만들고 내부에 index.js 들을 생성해주세요
// src/memos/index.js
import React from "react";
import styled from "styled-components";
const MemoFrame = styled.div``;
function Memos() {
return <MemoFrame>Memos</MemoFrame>;
}
export default Memos;
// src/content/index.js
import React from "react";
import styled from "styled-components";
const ContentFrame = styled.div``;
function Content() {
return <ContentFrame>Memo</ContentFrame>;
}
export default Content;
혹시 styled-component 의 사용법을 잘 모르신다면 이전 예제들을 확인해주세요
만들어진 컴포넌트들을 App.js 에서 불러와서 간단한 레이아웃 구조를 생성해보겠습니다.
// src/App.js
import React from "react";
import styled, { css } from "styled-components";
import Memos from "./memos";
import Content "./content";
// 왼쪽 오른쪽 구조를 나눠야 하기 때문에 flex 를 이용합니다.
const AppFrame = styled.div`
display: flex;
height: 100vh;
`;
/*
나눠진 왼쪽 오른쪽에 flex 사이즈를 유동적으로 조절하기 위해 flex 값을
props 로 내려받습니다.
*/
const Container = styled.div`
${({ flex }) =>
flex &&
css`
display: flex;
flex: ${flex};
`}
`;
function App() {
return (
<AppFrame>
<Container flex={1}>
<Memos />
</Container>
<Container flex={2}>
<Content />
</Container>
</AppFrame>
);
}
export default App;
아래와 같이 나누어진 화면을 보실 수 있을거에요
2) useContext 를 이용하여 Context API 구성
왼쪽 목록의 컴포넌트에서는 선택된 메모의 값을 알아야하고
오른쪽 컴포넌트에서는 선택된 메모 값을 바탕으로 데이터를 그려줘야합니다.
이처럼 컴포넌트들 끼리의 상호작용이 일어날때 가장 간단한 방법은
두 컴포넌트를 감싸는 컴포넌트로 state 를 올려서 사용하는 방법이 있지만
이번에는 Context API 를 이용하여 데이터를 주고 받는 방법을 알아보려고합니다.
use-Context 라는 hook 을 이용하여 Context API 를 보다 손쉽게 사용하도록 할 수 있습니다.
// src/application-context.js
import React, { createContext, useContext, useState } from "react";
// Context 를 생성합니다.
const Context = createContext(null);
// Provider 로 감싸지는 컴포넌트들은 value 의 값을 props 로 받을 수 있습니다.
export function ApplicationContextProvider({ children }) {
const [memos, setMemos] = useState(null);
const [memo, setMemo] = useState(null);
const value = {
memos,
setMemos,
memo,
setMemo
};
return <Context.Provider value={value}>{children}</Context.Provider>;
}
// 외부에서 context 를 손쉽게 가져다 쓸 수 있도록 도와줍니다.
export function useApplicationContext() {
return useContext(Context);
}
여기서 잠깐, useState 란 ?
useState 는 이전에 보았던 class component 의 state = { // ... } 와 같습니다. 다른 점이 있다면 setState 로 변경했던 것과는 다르게 useState 는 해당 state 를 변경 할 수 있는 짝을 지원해 준다는 것입니다.
const [count, setCount] = useState(0)
// count 의 값을 바꿀 수 있는 방법은 setCount 를 이용하는 방법뿐이다.
// naming 규칙은 보통 set + state 명 입니다.
3) 만들어진 Context API 이용하기
Context API 는 말그대도 관련있는 Context 에서만 값을 이용할 수 있도록 만들어 줄 수 있습니다.
하지만 지금 우리는 Context 범위가 적기 때문에 두 컴포넌트를 감싸고 있는 App.js 에서 Provider 를 적용해주도록 하겠습니다.
이제 Provider 로 감싸져 있는 내부 요소들에서는 useApplicationContext 를 이용하여 Context 내부 값에 접근 할 수 있습니다.
4) Memos 컴포넌트에서 Context API 사용하기
Memos 컴포넌트를 작성하기전에 먼저 Context API의 memos에 dummy data 를 채워보고자합니다.
메모는 아래와 같은 데이터 구조를 갖습니다.
id: number = '메모의 고유한 id'
title: string = '메모의 제목'
content: string = '메모의 내용'
useState 는 인자로 default value 를 줄 수 있습니다. memos 의 default Value 로 dummy data 가 추가된 배열을 줍니다.
import React, { createContext, useContext, useState } from "react";
const Context = createContext(null);
export function ApplicationContextProvider({ children }) {
// useState 의 default Value 를 이용하여 값을 채워줍니다.
const [memos, setMemos] = useState([
{
id: Date.now(),
title: "임시 메모 데이터",
content: "임시 메모 데이터의 내용"
}
]);
const [memo, setMemo] = useState(null);
const value = {
memos,
setMemos,
memo,
setMemo
};
return <Context.Provider value={value}>{children}</Context.Provider>;
}
export function useApplicationContext() {
return useContext(Context);
}
이제 memos 에서 context api 에 접근하여 memos 데이터가 잘 불러와지는지 확인해보겠습니다.
// src/memos/index.js
import React from "react";
import styled from "styled-components";
import { useApplicationContext } from "../application-context";
const MemosFrame = styled.div``;
function Memos() {
const { memos } = useApplicationContext();
console.log("memos", memos);
return <MemosFrame>Memos</MemosFrame>;
}
export default Memos;
memos 데이터를 가지고 왼쪽 리스트를 구성해야하는데 레이아웃 그림에서 보신 것 처럼 같은 형식의 구조가 반복되어지고 있습니다.
이 컴포넌트를 리스트자체에서 그려주는 것 보다는 memo 라는 컴포넌트를 만들어 따로 그려주는것이 렌더링 이점과 사용 측면에서도 좋기 때문에 따로 분리를 하겠습니다.
memo 컴포넌트는 id, title, content 의 데이터를 props 로 받습니다.
// src/memo/index.js
import React from "react";
import styled from "styled-components";
const MemoFrame = styled.div``;
function Memo({ source: { title, content }}) {
return <MemoFrame>Memo</MemoFrame>;
}
export default Memo;
만든 Memo 를 Memo 에서 사용하도록 추가합니다.
// src/memos/index.js
import React from "react";
import styled from "styled-components";
import { useApplicationContext } from "../application-context";
import Memo from "../memo";
// MemosFrame style 을 추가합니다.
const MemosFrame = styled.div`
width: 100%;
padding: 10px;
box-sizing: border-box;
overflow-y: auto;
`;
function Memos() {
const { memos } = useApplicationContext();
console.log("memos", memos);
// 만들어진 Memo 를 가져와 사용합니다.
return (
<MemosFrame>
{memos.map(memo => (
<Memo key={memo.id} source={memo} />
))}
</MemosFrame>
);
}
export default Memos;
5) 공통 컴포넌트 만들기
다양한 텍스트를 표현하기 위해 공통적으로 사용할 Text 컴포넌트와
컴포넌트들을 감싸줄 Container 만들어보겠습니다.
Text 의 경우 당장의 필요한 속성은 텍스트의 사이즈, 굵기, 말줄임, line-height 입니다.
앞으로 필요한 속성은 하나씩 추가하면서 살펴보겠습니다.