React로 nodebirdSNS 만들기 (인프런)/#2 SNS 화면 만들기

#2-4 커스텀 훅 재사용 및 홈 화면 설정,useCallback

정중식 2020. 1. 7. 12:39

쪼개기

- 리액트는 한 페이지에서 모든걸 다 만들면 여러 컴포넌트가 리랜더링 되기때문에 별도의 컴포넌트로 나눠주는게좋다.

 (*쪼개면 부모컴포넌트, 자식컴포넌트로 나눠지기때문에 관리에 약간의 어려움이 있는건 사실.*)

 

 

 

- components폴더-> LoginForm.js

import React, { useState, useCallback } from "react";
import Link from "next/link";
import { Form, Input, Button } from "antd";
import { useInput } from "../pages/signup";

// useCallback으로 감싸는 함수기준은 자식 컴포넌트에 넘겨주는 함수는 무조건 감싸준다고 보면됨
const LoginForm = () => {
  const [id, onChangeId] = useInput("");
  const [password, onChangePassword] = useInput("");
  const onSubmitForm = useCallback(
    e => {
      e.preventDefault();
      console.log({
        id,
        password
      });
    },
    [id, password]
  );

  return (
    <Form onSubmit={onSubmitForm}>
      <div>
        <label htmlFor="user-id">아이디</label>
        <br />
        <Input name="user-id" value={id} onChange={onChangeId} required />
      </div>
      <div>
        <label htmlFor="user-password">비밀번호</label>
        <br />
        <Input
          name="user-password"
          type="password"
          value={password}
          required
          onChange={onChangePassword}
        />
      </div>
      <div>
        <Button type="primary" htmlType={"submit"} loading={false}>
          로그인
        </Button>
        <Link href="/signup">
          <a>
            <Button>회원가입</Button>
          </a>
        </Link>
      </div>
    </Form>
  );
};

export default LoginForm;

- AppLayout.js

import React, { children } from "react";
import Link from "next/link";
import PropTypes from "prop-types";
import { Menu, Input, Row, Col, Card, Avatar, Form } from "antd";
import LoginForm from "./LoginForm";

// 가짜 데이터
const dummy = {
  nickname: "정중식",
  Post: [],
  Following: [],
  Follower: [],
  isLoggedIn: false
};

const AppLayout = ({ children }) => {
  return (
    <div>
      <Menu mode="horizontal">
        <Menu.Item key="home">
          <Link href="/">
            <a>노드버드</a>
          </Link>
        </Menu.Item>
        <Menu.Item key="profile">
          <Link href="/profile">
            <a>프로필</a>
          </Link>
        </Menu.Item>
        <Menu.Item key="mail">
          <Input.Search enterButton style={{ verticalAlign: "middle" }} />
        </Menu.Item>
      </Menu>

      <Row>
        <Col xs={24} md={6}>
          {dummy.isLoggedIn ? (
            <Card
              actions={[
                <div key="twit">
                  짹짹
                  <br />
                  {dummy.Post.length}
                </div>,
                <div key="following">
                  팔로잉
                  <br />
                  {dummy.Following.length}
                </div>,
                <div key="follower">
                  팔로워
                  <br />
                  {dummy.Follower.length}
                </div>
              ]}
            >
              <Card.Meta
                avatar={<Avatar>{dummy.nickname[0]}</Avatar>}
                title={dummy.nickname}
              />
            </Card>
          ) : (
            <LoginForm />
          )}
        </Col>
        <Col xs={24} md={12}>
          {children}
        </Col>
        <Col xs={24} md={6}></Col>
      </Row>
    </div>
  );
};

AppLayout.propTypes = {
  children: PropTypes.node
};

export default AppLayout;

커스텀 훅 재사용

- signup.js파일에서 사용한 커스텀 훅을 LoginForm.js 파일에서도 사용해준다

 

- 커스텀 훅은 리액트에서 form 처리 이벤트 중복을 최소화시켜줘서 좋다.

// 커스텀 훅
export const useInput = (initValue = null) => {
  const [value, setter] = useState(initValue);
  const handler = useCallback(e => {
    setter(e.target.value);
  }, []);
  return [value, handler];
};

useCallBack()

- useCallback으로 감싸는 함수기준은 자식 컴포넌트에 넘겨주는 함수는 무조건 감싸준다고 보면됨

 

- jsx에 들어가는 함수인 경우에 useCallback으로 감싸주셔야 합니다. <button onClick={onClick}>처럼 jsx에 들어가는 onClick에요.

 

- 감싸주지 않으면 onClick 함수가 리렌더링 시마다 새로 만들어집니다. 함수를 새로 만드는 것은 낭비입니다. 새로 만들어지는 것을 막기 위해서 []를 사용하는 거고, 새로 만들어주어야 하는 특별한 경우가 생기는데(useCallback에서 사용하는 state가 바뀐다거나) 그럴 때 새로 만드는 기준이 될 state를 배열 안에 넣어줍니다.

   .[] 빈 대괄호는 한번만 리렌더링 된다는뜻이고, 대괄호안에 새로만드는 기준이될 state를 배열안에넣어주면 []안의 내용이 바뀔때마다 리렌더링 , 즉 함수가 새롭게 생성됨