next에서 nprogress사용해보기

|

next에서 nprogress사용해보기

유데미 강의 next.js를 보고 생소한 기능을 메모했습니다. 틀린 내용은 댓글로 편하게 알려주세요!

nprogress란?

  • 프론트엔드 개발할 때 언제나 필요한 기능 중 하나가 서버의 응답을 기다리는 동안에 보여줄 로딩 표시이다. 이 로딩 표시를 간단하게 구현해준다.

nprogress사용

  • cdnjs로 가서 nprogress.css코드를 긁어온다.

  • 아래 코드 참고

핵심 코드 기입

태그 안에있는 link는 _document.js파일안에 넣어서 보관하기도한다.
<Head>
  <title>NextPortfolio</title>
  <link
    rel="stylesheet"
    href="https://cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.css"
  />
</Head>;

// 라우터이동할때 로딩 설정
Router.onRouteChangeStart = (url) => {
  console.log(url);
  NProgress.start();
};
// 라우터이동이 완료했을때 설정
Router.onRouteChangeComplete = () => {
  NProgress.done();
};
// 라우터에러발생했을때 로딩 설정
Router.onRouteChangeError = () => {
  NProgress.done();
};

전체 코드

import React from "react";
import Link from "next/link";
import Head from "next/head";
import Router from "next/router";
import NProgress from "nprogress";

// 라우터이동할때 로딩 설정
Router.onRouteChangeStart = (url) => {
  console.log(url);
  NProgress.start();
};
// 라우터이동이 완료했을때 설정
Router.onRouteChangeComplete = () => {
  NProgress.done();
};
// 라우터에러발생했을때 로딩 설정
Router.onRouteChangeError = () => {
  NProgress.done();
};
const Layout = ({ children, title }) => {
  return (
    <div className="root">
      <Head>
        <title>NextPortfolio</title>
        <link
          rel="stylesheet"
          href="https://cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.css"
        />
      </Head>
      <header>
        <Link href="/">
          <a>Home</a>
        </Link>
        <Link href="/about">
          <a>About</a>
        </Link>
        <Link href="/hireme">
          <a>Hire Me</a>
        </Link>
      </header>

      <h1>{title}</h1>
      {children}

      <footer>&copy; {new Date().getFullYear()}</footer>
    </div>
  );
};

export default Layout;

작동 화면

views
헤더부분 맨 오른쪽에 라우터 경로가 바뀔때마다 파란색 동그라미로 로딩표시가 뜬다.콘솔창에는 바뀐 url경로가 출력된다.

Next _document.js커스텀마이징

|

Next _document.js커스텀마이징

_document.js

개인적으로 index.css기능이라고 생각합니다.

  • next에서 보통 레이아웃은 _app.js에서하거나, AppLayout.js를 구현후 _app.js에서 import AppLayout해서 레이아웃을 구성한다.하지만 html이나 body 속성을 추가해야한다면 _documents.js가 필요하다.

  • pages/_document.js 형태로 존재해야 한다.

  • 이외에도 styled-Components를 사용하려면 _documents.js파일을 커스텀마이징 해야한다.

_documents.js만져보기

  • 폰트 설정과 글로벌 css 설정 및 중복되는link href 적용하기
import Document, { Head, Main, NextScript } from "next/document";

export default class MyDocument extends Document {
  render() {
    return (
      <html lang="ko-KR">
        <Head>
          <meta
            name="description"
            content="A site for my programing portfolio"
          />
          <meta charSet="utf-8" />
          <meta name="robots" content="noindex,nofollow" />
          <meta name="viewport" content="width=device-width" />
          <link
            rel="stylesheet"
            href="https://cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.css"
          />
          <link
            href="https://fonts.googleapis.com/css?family=Roboto"
            rel="stylesheet"
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
        <style global jsx>{`
          body {
            font-family: "Roboto", sans-serif;
          }
        `}</style>
      </html>
    );
  }
}

react,next 01. 실습 1 Ant Design 사용해보기

|

react,next 01. 실습 1 Ant Design 사용해보기

세팅자료

  • 실습겸 기초 세팅까지 진행했다.

  • ant Design을 사용하여 로그인 폼을 구현했다.

views
로그인 폼 구현 화면

react,next 01. prop-types

|

prop-types

prop-types란?

npm자료.. npm i prop-types

  • 타입의 유형을 검사한다.

  • 컴포넌트 부모로부터 올바른 자료형(타입)을 받았는지 검사해주는 기능이다.

import PropTypes from "prop-types";

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

사용

import React from "react";
import Head from "next/head";
import PropTypes from "prop-types";
import AppLayout from "../components/AppLayout";

const NodeBird = ({ Component }) => {
  return (
    <>
      <Head>
        <title>NodeBird</title>
        <link
          rel="stylesheet"
          href="https://cdnjs.cloudflare.com/ajax/libs/antd/3.23.1/antd.css"
        />
      </Head>
      <AppLayout>
        <Component />
      </AppLayout>
    </>
  );
};

NodeBird.propTypes = {
  Component: PropTypes.elementType,
};

export default NodeBird;
  • children에 어떤 유형이 왔으면 하는지 propTypes ={} 로 적어준다.

  • 타입유형에 어긋나게 사용시, 화면 렌더링은 잘 되나 콘솔에 에러가 나온다.

타입 유형들

타입유형들은 prop-types npm으로 가면 적혀습니다.
한글로 설명을 번역시켜 긁어왔습니다.

MyComponent.propTypes = {
   //  prop이 특정 JS 프리미티브임을 선언 할 수 있습니다. 기본적으로
  //  모두 선택 사항입니다
  optionalArray: PropTypes.array,
  optionalBool: PropTypes.bool,
  optionalFunc: PropTypes.func,
  optionalNumber: PropTypes.number,
  optionalObject: PropTypes.object,
  optionalString: PropTypes.string,
  optionalSymbol: PropTypes.symbol,

  //  렌더링 할 수있는 것 : 숫자, 문자열, 요소 또는 배열
  //  이러한 유형을 포함하는 (또는 조각)
  optionalNode: PropTypes.node,

  //  React 요소 (예 : <MyComponent />)
  optionalElement: PropTypes.element,

  //  React 요소 유형 (예 : MyComponent).
  optionalElementType: PropTypes.elementType,

  //  prop이 클래스의 인스턴스라고 선언 할 수도 있습니다. 이것은 사용
  //  JS의 instanceof 연산자.
  optionalMessage: PropTypes.instanceOf(Message),

  //  치료를 통해 소품이 특정 값으로 제한되도록 할 수 있습니다
  //  열거 형입니다.
  optionalEnum: PropTypes.oneOf(['News', 'Photos']),

  //  여러 유형 중 하나 일 수있는 객체
  optionalUnion: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.number,
    PropTypes.instanceOf(Message)
  ]),

  //  특정 유형의 배열
  optionalArrayOf: PropTypes.arrayOf(PropTypes.number),

  //  특정 유형의 속성 값을 가진 개체
  optionalObjectOf: PropTypes.objectOf(PropTypes.number),

  //  위의 내용을`isRequired`와 연결하여 경고를 확인할 수 있습니다.
  //  소품이 제공되지 않으면 표시됩니다.

  //  특정 모양을 취하는 객체
  optionalObjectWithShape: PropTypes.shape({
    optionalProperty: PropTypes.string,
    requiredProperty: PropTypes.number.isRequired
  }),

  //  추가 속성에 대한 경고가있는 객체
  optionalObjectWithStrictShape: PropTypes.exact({
    optionalProperty: PropTypes.string,
    requiredProperty: PropTypes.number.isRequired
  }),

  requiredFunc: PropTypes.func.isRequired,

  //  모든 데이터 유형의 값
  requiredAny: PropTypes.any.isRequired,

  //  사용자 지정 유효성 검사기를 지정할 수도 있습니다. 오류를 반환해야합니다
  //  유효성 검사에 실패한 경우 이의 제기 `console.warn`하거나 던지지 마십시오.
  //  `oneOfType`에서는 작동하지 않습니다.
  customProp: function(props, propName, componentName) {
    if (!/matchme/.test(props[propName])) {
      return new Error(
        'Invalid prop `' + propName + '` supplied to' +
        ' `' + componentName + '`. Validation failed.'
      );
    }
  },

  //  `arrayOf`와`objectOf`에 커스텀 유효성 검사기를 제공 할 수도 있습니다.
  //  유효성 검사에 실패하면 Error 개체를 반환해야합니다. 유효성 검사기
  //  배열 또는 객체의 각 키에 대해 호출됩니다. 처음 두
  //  유효성 검사기의 인수는 배열 또는 객체 자체이며
  //  현재 아이템의 키.
  customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
    if (!/matchme/.test(propValue[key])) {
      return new Error(
        'Invalid prop `' + propFullName + '` supplied to' +
        ' `' + componentName + '`. Validation failed.'
      );
    }
  })
};

react,next dummy데이터 사용해보기

|

react,next dummy데이터 사용해보기

현업에서 백엔드 개발자와 작업을 할 때, 백엔드 서버가 아직 완성되지않았을때 프론트에서 dummy 데이터를 사용하여 임시로 작업하는 방법입니다.

사용예시

const dummy = {
  nickname: "정중식",
  Post: [],
  Following: [],
  Followers: [],
};

<Row>
  <Col xs={24} md={6}>
    {/* 유저정보 */}
    <Card
      actions={[
        <div key="twit">
          짹짹
          <br />
          {dummy.Post.length}
        </div>,
        <div key="following">
          팔로잉
          <br />
          {dummy.Post.Following.length}
        </div>,
        <div key="follower">
          팔로워
          <br />
          {dummy.Post.Follower.length}
        </div>,
      ]}
    >
      <Card.Meta
        avatar={<Avatar>{dummy.nickname[0]}</Avatar>}
        title={dummy.nickname}
      />
    </Card>
  </Col>
  <Col xs={24} md={12}>
    {children}
  </Col>
  <Col xs={24} md={6}>
    세번째
  </Col>
</Row>;

심화

isLoggedIn을 이용해서 로그인했을때의 화면과 로그인 안했을때의 화면을 분류해줄 수 있습니다.

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

const dummy = {
  nickname: "정중식",
  Post: [],
  Following: [],
  Followers: [],
  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="email">
          <Input.Search enterButton style= />
        </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.Followers.length}
                </div>,
              ]}
            >
              <Card.Meta
                avatar={<Avatar>{dummy.nickname[0]}</Avatar>}
                title={dummy.nickname}
              />
            </Card>
          ) : (
            <Form>
              <div>
                <label htmlFor="user-id">아이디</label>
                <br />
                <Input
                  name="user-id"
                  // value={userId}
                  // onChange={onChangeId}
                  required
                />
              </div>
              <div>
                <label htmlFor="user-password">비밀번호</label>
                <br />
                <Input
                  name="user-password"
                  type="password"
                  // value={password}
                  // onChange={onChangePassword}
                  required
                />
              </div>
              <div>
                <Button type="primary" htmlType="submit" loading={false}>
                  로그인
                </Button>
                <Link href="/signup">
                  <a>
                    <Button>회원가입</Button>
                  </a>
                </Link>
              </div>
            </Form>
          )}
        </Col>
        <Col xs={24} md={12}>
          {children}
        </Col>
        <Col xs={24} md={6}>
          세번째
        </Col>
      </Row>
    </div>
  );
};

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

export default AppLayout;