[카테캠] 2단계 - week 2

werthers·2023년 7월 4일
0

카카오테크캠퍼스

목록 보기
12/16
post-thumbnail

아토믹 패턴으로 컴포넌트 관리

  • 컴포넌트가 많을 경우 재사용성 을 위해 사용하는 패턴
  • Atoms
    • 가장 작은 단위의 컴포넌트 모음
    • UI 디자인 상 더 이상 나눌 수 없는 기준이 되는 컴포넌트 / 최소 수준의 HTML 엘리먼트
    • 내부 상태가 없거나 최소화된 Presentational Components
    • 저레벨 컴포넌트에서 상태 변화를 최소화 하는 것이 좋다.
  • Molecules
    • Atom 레벨의 컴포넌트가 합쳐져 만들어지는 컴포넌트 모음
    • 콘텐츠 카드, 캐러셀 등을 관리하는 레벨
    • 무조건 Atom레벨 컴포넌트를 포함할 필요는 없다.
  • Organisms
    • Molecule 이나 Atom 레벨의 컴포넌트가 포함된 상위 레벨
  • Templates
    • 여러 Organisms 레벨 컴포넌트를 포함한 상위 컴포넌트 모음
    • Page 바로 아래 단계
  • High to Low
    • 아토믹 패턴에서 데이터는 상위 레벨에서 하위 레벨로 진행
    • 상위 컴포넌트에서 Props를 전달하여 이벤트를 받거나 글로벌 상태 관리를 사용

Atoms 만들기

  • Input.jsx
    const Input = ({ type, value, onChange, placeholder, className, id, name }) => {
      return (
        <input
          type={type}
          value={value}
          onChange={onChange}
          placeholder={placeholder}
          className={className}
          id={id}
          name={name}
        />
      );
    };
    
    export default Input;
  • Label.jsx
    const Label = ({ htmlFor, children, className }) => {
      return (
        <label htmlFor={htmlFor} className={className}>
          {children}
        </label>
      );
    };
    
    export default Label;
  • Button.jsx
    const Button = ({ onClick, chlidren }) => {
      return (
        <button
          onClick={(e) => {
            e.preventDefault();
            onClick();
          }}
        >
          {chlidren}
        </button>
      );
    };
    
    export default Button;
  • Container.jsx
    import "../../styles/atoms/Container.css";
    
    const Container = ({ children, className }) => {
      return <div className={`container ${className}`}>{children}</div>;
    };
    
    export default Container;
  • Box.jsx
    import "../../styles/atoms/Box.css";
    
    const Box = ({ className = "", children }) => {
      return <div className={`box ${className}`}>{children}</div>;
    };
    
    export default Box;

molecules organisms pages 폴더 생성 및 컴포넌트 만들기

  • molecules/InputGroup.jsx
    import Input from "../atoms/Input";
    import Box from "../atoms/Box";
    import Label from "../atoms/Label";
    
    const InputGroup = ({ id, type, name, value, onChange, className, label }) => {
      return (
        <Box className={className}>
          <Label htmlFor={id}>{label}</Label>
          <Input
            id={id}
            name={name}
            type={type}
            value={value}
            onChange={onChange}
          />
        </Box>
      );
    };
    
    export default InputGroup;
  • organisms/RegisterForm.jsx
    import Container from "../atoms/Container";
    import InputGroup from "../molecules/InputGroup";
    import Button from "../atoms/Button";
    import useInput from "../../hooks/useInput";
    import { register } from "../../services/api.js";
    import { useEffect } from "react";
    const RegisterForm = () => {
      const { value, handleOnChange } = useInput({
        username: "",
        email: "",
        password: "",
        passwordConfirm: "",
      });
    
      return (
        <Container>
          <InputGroup
            id="username"
            type="text"
            placeholder="사용자 이름을 입력해주세요"
            label="이름"
            name="username"
            value={value.username}
            onChange={handleOnChange}
          />
          <InputGroup
            id="email"
            type="email"
            placeholder="이메일을 입력해주세요"
            label="이메일"
            name="email"
            value={value.email}
            onChange={handleOnChange}
          />
          <InputGroup
            id="password"
            type="password"
            name="password"
            placeholder="********"
            label="비밀번호"
            value={value.password}
            onChange={handleOnChange}
          />
          <InputGroup
            id="passwordConfirm"
            type="password"
            name="passwordConfirm"
            placeholder="********"
            label="비밀번호 확인"
            value={value.passwordConfirm}
            onChange={handleOnChange}
          />
          <Button
            onClick={() => {
              register({
                email: value.email,
                password: value.password,
                username: value.username,
              });
            }}
          >
            회원가입
          </Button>
        </Container>
      );
    };
    export default RegisterForm;
  • pages/RegisterPage.jsx
    import RegisterForm from "../components/organisms/RegisterForm";
    
    const RegisterPage = () => {
      return <RegisterForm />;
    };
    
    export default RegisterPage;

커스텀 훅 / 회원가입 폼 제출 시 api 만들기

  • useRef를 중복해서 선언하지 않기 위해 커스텀 훅 useInput을 만든다.
    import { useState } from "react";
    const useInput = (initialValue) => {
      const [value, setValue] = useState(initialValue);
    
      const handleOnChange = (e) => {
        const { name, value } = e.target;
        setValue((prev) => ({ ...prev, [name]: value }));
      };
      return { value, handleOnChange };
    };
    
    export default useInput;
    • 이렇게 만들게 되면 RegisterForm.jsx에서 각각의 useRef를 생성하지 않고 useInput을 통해 [e.target](http://e.target)value, name 이 각각 onChange 이벤트 발생 시 value 객체에 담기게 될 수 있다.
    • 또한 prev 를 통해 이전 값을 저장하고, 새로운 이벤트의 값을 추가해주는 것이 안전한 방법이다.
  • src/services 를 통해 api.js만들기
    export const register = (data) => {
      const { email, password, username } = data;
      return instance.post("/join", {
        email,
        password,
        username,
      });
    };
    • fetch를 사용한 방법도 있지만 npm i axios를 통해 axios로 회원가입 버튼을 눌렀을 때 각각의 username, password, emaildata로 넘겨받아 /join 으로 값을 넘겨주며 post요청을 하는 api를 만들었다.
    • 또한 importdefault가 아니기 때문에 중괄호를 통해 register함수를 넘겨받아 RegisterForm.jsx에서 버튼 클릭 시 처리되도록 한다.
  • .envapi.js에서 인스턴스로 사용될 baseURL을 관리한다.
profile
Hello World !

0개의 댓글