wowjs를 활용하여 리액트에서 애니메이션 구현하기

|

wowjs를 활용하여 리액트에서 애니메이션 구현하기

wowjs깃허브주소:wowjs
구현 할 수 있는 css목록들:animate

wowJs사용전 준비단계

최신버전인 4.1.0 링크코드를 복붙했으나 css가 동작하지않았습니다. 혹시 이 글을 보고 최신버전으로 사용해보신분은 댓글로 알려주시면 감사하겠습니다!

  • npm i wowjs

  • public/index.html파일의 head태그 안에 다음 코드를 복사 붙여넣기

  <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css"
    />

wowJs사용

className에 wow를 넣고,적용할 애니메이션 이름을 넣으면 됩니다. 이후 옵션을넣으면됩니다. 자세한건 wowjs 참고해주세요.

  • index.css
body {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
}

.center {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 80vh;
  width: 100%;
}

.center-photo {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  height: 80vh;
  width: 100%;
}

h1 {
  font-size: 4em;
}

.photo {
  max-height: 200px;
}

  • App.js
import React, { useEffect } from 'react';
import WOW from 'wowjs';

const App = () => {
  useEffect(() => {
    new WOW.WOW().init();
  }, []);

  return (
    <div>
      <div className='center'>
        <h1 className='wow flipInY' data-wow-iteration='1'>
          Hello Word!
        </h1>
        <p>a how to about WOW.js</p>
      </div>

      {/* offset은 요소까지의 거리 기본값은 0. 이라고 설명되어있는데,
      유저가 보는 화면 스크롤?이 어느정도왔을때 애니메이션이 발동되는지를 말하는듯 하다 */}
      <div className='center-photo'>
        <img
          className='photo wow fadeInDown'
          data-wow-iteration='1'
          data-wow-offset='80'
          data-wow-delay='.5s'
          src='/alaska1.jpg'
          alt='views'
        />
        <img
          className='photo WOW fadeInDown'
          data-wow-iteration='1'
          data-wow-offset='80'
          data-wow-delay='.75s'
          src='/alaska2.jpg'
          alt='views'
        />
        <img
          className='photo WOW fadeInDown'
          data-wow-iteration='1'
          data-wow-offset='80'
          data-wow-delay='1s'
          src='/alaska3.jpg'
          alt='views'
        />
      </div>
    </div>
  );
};

export default App;

결과물

views

DevConnector 프로젝트 00 - 초기세팅

|

DevConnector 프로젝트 00 - 초기세팅

유데미 강의를 보며 정리한 내용입니다. 영어로 듣고 화면만 보며 따라치고 잘 모르겠는 개념이 나오면 구글링후 메모하는 용도로 만들었습니다.
틀린 내용이 있다면 편하게 댓글로 알려주세요!

초기 세팅

npm i express express-validator bcryptjs request config gravatar jsonwebtoken mongoose axios
npm i -D nodemon concurrently
  • express-validator: 유효값 검사를 한다. Ex)회원가입시 중복된 닉네임 혹은 이메일 검사

  • concurrently:리액트 서버와 express 서버를 동시 실행해주는 역할을 한다.

  • npm i request: 브라우저에서 자바스크립트를 쓴다면 Fetch라는 내장 모듈이 있지만 Node.js에서 가장 많이 HTTP 네트워크 라이브러리는 단연 Request.js이다.

  • gravatar: 아바타를 편하게 가져와준다.

server.js 및 라우터

이 강의에서는 프론트서버만 나누고, 서버폴더를 따로 두지않습니다.(아직 까진 서버쪽 세팅중이라 프론트폴더는 생성 전 입니다.)
기본적인 라우터를 생성 및 연결하고, config/db.js를 불러와 서버에 몽고db를 연결해줍니다.

  • server.js
const express = require('express');
const connectDB = require('./config/db');

const app = express();

// Connect Database
connectDB();

app.get('/', (req, res) => res.send('API Running'));

// Define Routes
app.use('/api/users', require('./routes/api/users'));
app.use('/api/auth', require('./routes/api/auth'));
app.use('/api/profile', require('./routes/api/profile'));
app.use('/api/posts', require('./routes/api/posts'));

const PORT = process.env.PORT || 5000;

app.listen(PORT, () => console.log(`Server started on port${PORT}`));
  • routes/api/auth

    이후 routes/api/users,posts,profile파일도 다 똑같이 세팅

const express = require('express');
const router = express.Router();

// @route   Get api/auth
// @desc    Test route
// @access  Public
router.get('/', (req, res) => res.send('User route'));

module.exports = router;

config폴더 구성 및 db.js

  • config/db.js
const mongoose = require('mongoose');
const config = require('config');
const db = config.get('mongoURI');

const connectDB = async () => {
  try {
    await mongoose.connect(db, {
      useUnifiedTopology: true,
      useNewUrlParser: true,
    });

    console.log('MongoDB Connected...');
  } catch (err) {
    console.error(err.message);
    // 실패한 프로세스 종료
    process.exit(1);
  }
};

module.exports = connectDB;
  • config/default.json
{
  "mongoURI": "mongodb+srv://<몽고ID>:<password>@@cluster0.pr8qg.mongodb.net/<dbname>?retryWrites=true&w=majority"
}

최종 프로젝트 구조

views

: 이 카테고리는 개인 메모를 하는곳이므로, 이후 개발진행과정은 자세한 포스팅은 하지않겠습니다.

next에서 동적으로 쿼리파라미터 변수받기

|

next에서 동적으로 쿼리파라미터 변수받기

pages/blog.js

import Layout from "../components/Layout";
import React from "react";
import Link from "next/link";

const PostLink = ({ title }) => {
  return (
    <li>
      <Link href={`/post?title=${title}`}>
        <a>{title}</a>
      </Link>
    </li>
  );
};

const blog = () => {
  return (
    <Layout title="My Blog">
      <ul>
        <PostLink title="react" />
        <PostLink title="angular" />
        <PostLink title="vue" />
      </ul>
    </Layout>
  );
};

export default blog;

pages/post.js

  • withRouter를 이용하여 파라미터로 ({router})을 받는다.
import React from "react";
import Layout from "../components/Layout";
import { withRouter } from "next/router";

const Post = ({ router }) => {
  return (
    <Layout title={router.query.title}>
      <p>
        Lorem Ipsum is simply dummy text of the printing and typesetting
        industry. Lorem Ipsum has been the industry's standard dummy text ever
        since the 1500s, when an unknown printer took a galley of type and
        scrambled it to make a type specimen book.
      </p>
    </Layout>
  );
};

export default withRouter(Post);

보다 깨끗한 url만들기

위의 코드처럼 하면 url에 http://localhost:3000/post?title=react 이런식으로 지저분하게 나옵니다. 조금 더 깨끗한 url로 만들어봅시다.

  • Link 태그에 as를 활용한다.
import Layout from "../components/Layout";
import React from "react";
import Link from "next/link";

const PostLink = ({ slug, title }) => {
  return (
    <li>
      <Link as={`/${slug}`} href={`/post?title=${title}`}>
        <a>{title}</a>
      </Link>
    </li>
  );
};

const blog = () => {
  return (
    <Layout title="My Blog">
      <ul>
        <PostLink slug="react-post" title="React Post" />
        <PostLink slug="angular-post" title="Angular Post" />
        <PostLink slug="vue-post" title="Vue Post" />
      </ul>
    </Layout>
  );
};

export default blog;

결과

  • http://localhost:3000/react-post
  • http://localhost:3000/angular-post
  • http://localhost:3000/vue-post

next에서 customErrorPage 설정해보기

|

next에서 customErrorPage 설정해보기

에러가 발생했을때 에러 페이지를 설정해봅니다.

_error.js 커스텀 마이징하기

  • 넥스트에선 _error.js파일이라는 에러발생시 보여주는 화면을 커스텀마이징 할 수 있다.

pages/about.js

  • const statusCode = res.status > 200 ? res.status : false; 이 부분을 중점으로 보면될것 같다.
import React, { Component, useEffect, useState } from "react";
import Link from "next/link";
import fetch from "isomorphic-unfetch";
import Layout from "../components/Layout";
import Error from "./_error";

const About = ({ user, statusCode }) => {
  About.getInitialProps = async () => {
    const res = await fetch("https://api.github.com/users/jungsikjeong");
    const statusCode = res.status > 200 ? res.status : false;
    const data = await res.json();

    return { user: data, statusCode };
  };

  if (statusCode) {
    console.log(statusCode);
    return <Error statusCode={statusCode} />;
  }

  // const { user, statusCode } = props;
  return (
    <Layout title="About">
      <p>{user.name}</p>

      <p>A javaScript programmer</p>
      <img src={user.avatar_url} alt="Reed" height="200px" />
    </Layout>
  );
};

export default About;

_error.js

import Layout from "../components/Layout";

export default ({ statusCode }) => (
  <Layout title="Error!!!">
    {statusCode
      ? `사용자 데이터를 로드 할 수 없습니다: Status code ${statusCode}`
      : `해당 페이지를 가져올 수 없습니다. 죄송합니다`}
  </Layout>
);

getInitialProps로 api데이터 가져오기

|

getInitialProps로 api데이터 가져오기

getInitialProps란?

  • next는 서버로부터 동적인 데이터를 가져오지 못한다.그래서 프론트에서 동적인데이터를 사용 할 수 있게끔 도와주는 함수이다.

  • 컴포넌트디드마운트,컴포넌트윌마운트 같은 라이프사이클의 일종으로 넥스트가 임의로 추가해준 라이프 사이클이다.

  • 어떤 작업보다도 최초로 실행된다. (이후에 서버사이드랜더링할때도 getInitialProps를 활용하는듯하다.)

사용

isomorphic-unfetch는 데이터를 가져올 때 사용할 라이브러리입니다. 브라우저 fetch API 구현을 간단히 할 수 있도록 만들어진 것입니다.

npm i isomorphic-unfetch
import React, { Component, useEffect, useState } from "react";
import Link from "next/link";
import fetch from "isomorphic-unfetch";
import Layout from "../components/Layout";

const About = (props) => {
  About.getInitialProps = async () => {
    const res = await fetch("https://api.github.com/users/jungsikjeong");
    const data = await res.json();

    return { user: data };
  };

  const { user } = props;
  return (
    <Layout title="About">
      <p>{user.name}</p>
      {/* {JSON.stringify(props.user)} */}

      <p>A javaScript programmer</p>
      <img src={user.avatar_url} alt="Reed" height="200px" />
    </Layout>
  );
};

export default About;

개인적으로 사용하면서 헤맸던 부분

: About컴포넌트의 인자로 props를 안써줘서 화면에 null이 표시됬다. 화면에 뿌릴때도

JSON.stringify(props.user)

로 props.user를 사용하여 접근해야한다.
본문의 코드는 const { user } = props; es6문법을 사용해서 바로 접근할수 있게 해줬다.

코드 업데이트

import React, { Component, useEffect, useState } from "react";
import Link from "next/link";
import fetch from "isomorphic-unfetch";
import Layout from "../components/Layout";

const About = ({ user }) => {
  About.getInitialProps = async () => {
    const res = await fetch("https://api.github.com/users/jungsikjeong");
    const data = await res.json();

    return { user: data };
  };

  return (
    <Layout title="About">
      <p>{user.name}</p>
      {/* {JSON.stringify(props.user)} */}

      <p>A javaScript programmer</p>
      <img src={user.avatar_url} alt="Reed" height="200px" />
    </Layout>
  );
};

export default About;
  • props를 ({}) es6문법을써서 바로 가져올수있게해줬다.