기존에 만들어두었던 profile.js에 프로필 페이지를 구현해본다. 리액트에서 작업을 할 때 우선 렌더링할 기능 단위를 작은 컴포넌트로 나누어 설계를 하는 것이 좋다.

예를 들어 프로필 페이지에 NicknameEditForm와 FollowList 컴포넌트로 각 기능을 구현하겠다를 먼저 배치하고 이후에 상세 컴포넌트를 구현하는 방식이다.

// profile.js
import AppLayout from "../components/AppLayout";
import Head from "next/head";

import NicknameEditForm from "../components/NicknameEditForm";
import FollowList from "../components/FollowList";

const Profile = () => {
	// dummy data
  const followerList = [{ nickname: "비키" }, { nickname: "워니" }, { nickname: "썬" }];
  const followingList = [{ nickname: "비키" }, { nickname: "워니" }, { nickname: "썬" }];

  return (
    <>
      <Head>
        <title>내 프로필 | NodeBird</title>
      </Head>
      <AppLayout>
        <NicknameEditForm />
        <FollowList header="팔로잉 목록" data={followingList} />
        <FollowList header="팔로워 목록" data={followerList} />
      </AppLayout>
    </>
  );
};

export default Profile;

위에서 만든 NicknameEditForm와 FollowList 컴포넌트를 구현해본다.

// NicknameEditForm.js
import React, { useMemo } from "react";
import { Form, Input } from "antd";

const NicknameEditForm = () => {
  const style = useMemo(() => ({ marginBottom: 20, border: "1px solid #d9d9d9", padding: 20 }), []);

  return (
    <Form style={style}>
      <Input.Search addonBefore="닉네임" enterButton="수정" />
    </Form>
  );
};

export default NicknameEditForm;
// FollowList.js
import React, { useMemo } from "react";
import PropTypes from "prop-types";
import { List, Button, Card } from "antd";
import { StopOutlined } from "@ant-design/icons";

const FollowList = ({ header, data }) => {
  const listStyle = useMemo(() => ({ marginBottom: 20 }), []);
  const loadMoreStyle = useMemo(() => ({ textAlign: "center", margin: "10px 0" }), []);
  const renderListStyle = useMemo(() => ({ marginTop: 20 }), []);

  return (
    <List
      header={<div>{header}</div>}
      style={listStyle}
      grid={{ gutter: 4, xs: 2, md: 3 }}
      size="small"
      loadMore={
        <div style={loadMoreStyle}>
          <Button>더보기</Button>
        </div>
      }
      bordered
      dataSource={data}
      renderItem={(item) => (
        <List.Item style={renderListStyle}>
          <Card actions={[<StopOutlined key="stop" />]}>
            <Card.Meta description={item.nickname} />
          </Card>
        </List.Item>
      )}
    />
  );
};

FollowList.propTypes = {
  header: PropTypes.string.isRequired,
  data: PropTypes.array.isRequired,
};

export default FollowList;