PROGRAMMING

ナビゲーションバーを途中から出現させる【Reactjs】

今回ナビゲーションバーを最初から出現させるのではなくて、後からフワッと出てくるような機能をつける方法についてやっていきたいと思います。

こういう機能は結構難しくネットで書かれたりしてますが、初心者の僕は難しくは描けないので、簡単な方法を今回は紹介します。

まずは途中からナビゲーションバーが出てくるというイメージが出ないと思うので、イメージがつきやすいようにしたに貼っておきます。

上のように最初はナビゲーションバーは下にあるけど、途中までくると写真が出てきて、後からナビゲーションバーが出てくるようにしてあります。

この記事でわかること
・reactでナビゲーションバーを途中から出す方法
・アニメーションについて

今回はこんな感じでやっていきます。

Reactでナビゲーションバーの途中出現させる方法

ナビゲーションバーの設定

ナビゲーションバーのリンクをリストにする

まずはナビゲーションバーのリンク先をリストにしていきます。

export const menuData = [
  { title: 'ABOUT', link: '/about' },
  { title: 'MENU', link: '/menu' },
  { title: 'SHOP', link: '/shop' },
  { title: 'CONTACT', link: '/contact' },
];

こうすることで何回でも使い回すことができますね。

それではナビゲーションバーを作っていきます。

ナビゲーションバーの作成

ナビゲーションバーは左に寄せたシンプルなものにします。

import styled from 'styled-components';
 //styledコンポーネントを使ってデザインしていきます。
import { menuData } from '../data/MenuData';
//さっきのリンク先の一覧リストをインポートする
import { Link } from 'gatsby';
import React from 'react';

const ToppageNavbar = () => {
  return (
    <Nav>
      <NavContainer>
        <NavMenu>
          <NavItem>
            {menuData.map((items, index) => (
              <NavLinks to={items.link} key={index}>
                {items.title}
              </NavLinks>
            ))}
          </NavItem>
        </NavMenu>
      </NavContainer>
    </Nav>
  );
};

export default ToppageNavbar;
  
const Nav = styled.nav`
  background-color: #fff;
  display: flex;
  justify-content: flex-start;
  align-items: center;
  font-size: 1rem;
  position: sticky;
  top: 0;
  z-index: 999;
  display: flex;
`

const NavContainer = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
  max-width: 1400px;
  height: 80px;
`;

const NavMenu = styled.div`
  display: grid;
  grid-template-columns: repeat(4, auto);
  grid-gap: 15px;
  list-style: none;
  text-align: center;
  letter-spacing: 3px;
`

export const NavItem = styled.li`
  display: grid;
  grid-template-columns: repeat(4, auto);
  grid-gap: 15px;
  list-style: none;
  text-align: center;
`;

export const NavLinks = styled(Link)`
  color: #000;
  display: flex;
  align-items: center;
  text-decoration: none;
  padding: 0.5rem 1rem;
  height: 100%;
      &:hover {
      transform: translate(0%, -8%);
      opacity: 0.4;
      transition: 400ms;
    }
  
`;

ここではデザイン的なことは省きます。

styledコンポーネントについてわからない方は下記のページを見るといいと思います。

styled-componentsの使い方【初心者向け】|Watablog

今日は、Reactを採用したプロジェクトでは最も人気のある「styled-component」について、エンジニア初心者、もしくはバックエンドエンジニア向けに解説します。 僕は、ピュアなReactのプロジェクト以外にも、GatsbyJS, Next.js, Material-UIなどを導入したプロジェクトでも、「styled-component」を使っています。 「styled-component」は、CSS in JS の使い難い部分を解決してくれる最高のライブラリです。初心者向けに解説していきますが、前提として、Reactのコンポーネントを例に解説していきますので、React、CSS、そしてSassを程度理解している必要があります。 まずは、さらっと「CSS in JS」について説明しておきます。 CSS in JSとは読んで字の如く、.jsのJavaScriptファイルにCSSを書いていこうというものです。このような設計にすることにより、コンポーネントごとにコードを切り離して開発することができます。例えば、 header.jsというファイルに、ReactとCSSをまとめて書くことにより、コンポーネント思考の開発が可能になります。 コンポーネント思考の開発によるメリットは、 などが挙げられます。 具体例を挙げると、CSSを書くときにも、長ったらしい命名規則を気にする必要はなくなるし、必要ではなくなったレガシーなCSSを自信を持って削除できるようになるでしょう。 このように、コンポーネント思考の開発はエンジニアにとって開発のストレスを軽減できる ナイスな手法ですが、CSS in JSが流行り出した2016年ごろには、「styled-component」のようなライブラリーは存在しておらず、CSS in JS では、まだまだ不便な点が多かった記憶があります。その一番の理由が、オブジェクトリテラルによるCSSの記述です。以下で、オブジェクトリテラルについて具体的例を挙げておきます。 CSS in JSは、あくまで.jsファイルにCSSを書いていくので、通常はオブジェクトリテラルで書いていきます。つまり、CSSをJSのオブジェクトを記述するように書いていくということです。 コード例を挙げておきます。 CSS in JSでのオブジェクトリテラルでの例 import React from 'react'; import styled from 'styled-components'; // ここがstyled-componentを使っている箇所で,オブジェクトリテラルで記述。 const Heading = styled.h1({ color: "red", fontSize: "32px", textAlign: "center" }); const App = () => ( Hello Heading!!!

下記の部分では、mapメソッドを使ってmenuDataのデータを取り出します。

menuDataをitemsに格納して、 to={items.link}こうすることでlinkというプロパティのデータを取得することができます。

基本的にgatsbyとかreactはこの方法をよく使用します。

          <NavItem>
            {menuData.map((items, index) => (
              <NavLinks to={items.link} key={index}>
                {items.title}
              </NavLinks>
            ))}
          </NavItem>

これで下記のようにナビゲーションバーを作成することができましたね。

これでナビゲーションバーの作成ができました。

次に途中からナビゲーションバーが出てくるように機能を追加します。

ナビゲーションバー スクロール

useState, useEfect

まずはReact HooksのuseStateとuseEffectを使って機能を追加します。

この二つについては下記のページで詳しくわかりやすく記述されています。僕はよく参考にさせてもらっています。

ステートフックの利用法 - React

フック (hook) は React 16.8 で追加された新機能です。state などの React の機能を、クラスを書かずに使えるようになります。 フックの導入のページ で以下の例を挙げてフックの紹介を行いました: このコードをクラスによる等価版と比較しながらフックについて学び始めましょう。 以前 React でクラスを使っていたなら、このコードに馴染みがあるでしょう。 state は { count: 0 } から始まり、ユーザがボタンをクリックした時に this.setState() を呼ぶことで state.count をインクリメントします。このページの全体にわたってこのクラスからの例が出てきます。 補足 もっと現実的な例ではなくカウンタを使っているのはなぜか気になるかもしれません。フックについての第一歩の説明ですので API にフォーカスするためです。 念のため、React の関数コンポーネントとはこのようなものです: あるいはこのようなものです: これらのことを「ステートレスコンポーネント (stateless component)」だと理解していたかもしれません。今からこれらの内部で React の state を利用できるようにしているので、「関数コンポーネント (function component)」という名前を使用しましょう。 フックはクラスの内部では動作 しません 。クラスを書く代わりに使うものです。 この新しい例では、React から useState をインポートするところから始めましょう。 フックとは何?

それではある部分まで下がるとナビゲーションバーが出てくるようにします。

まずは下記のコードを先ほどのコードに追加します。

+ import React, {useState, useEffect} from 'react'

const ToppageNavbar = () => {
  const [navbar, setNavbar] = useState(false)
  //navbarの初期値はfalseにする //setNavbarでnavbarの値をtrueかfalseにする

  useEffect(() => {
    const scrollNav = () => {
      if (window.scrollY >= 780) {
     //scrollYで縦方向に指定 //値がマイナスの場合は上方向
        setNavbar(true);
        //指定された値まで下に行くとnavbarの値がtrueになる
      }else{
        setNavbar(false);
      }
    };
    scrollNav()
    window.addEventListener("scroll", scrollNav)
   //イベントのスクロールがされることで、scrollNav関数が実行されます //これがないとスクロールしても実行されない

    return () => {
      window.removeEventListener('scroll', scrollNav);
   //scrollNav関数がスクロールされるたびに実行されてしまうので、イベントを削除する必要がある
    };


  }, [])

  return (
//navbarの値をactiveに代入する
   <Nav active = {navbar} >
      <NavContainer>
        <NavMenu>
          <NavItem>
            {menuData.map((items, index) => (
              <NavLinks to={items.link} key={index}>
                {items.title}
              </NavLinks>
            ))}
          </NavItem>
        </NavMenu>
      </NavContainer>
    </Nav>
  );
};

export default ToppageNavbar;

const Nav = styled.nav`
  background-color: #fff;
  display: flex;
  justify-content: flex-start;
  align-items: center;
  font-size: 1rem;
  position: sticky;
  top: 0;
  z-index: 999;
  display: ${({ active }) => (active ? "flex" : "none")};
//navbarがtrueになるとdisplayがflexになって、出てくる
`

こんな感じでスクロールすると関数実行されます。

removeEventListenerの必要性についてはいろいろあります。

これがないと下記のようなエラーが出ます。

Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

そのためremoveEventListenerをいれる必要性があります。

そのほかにも必要性は下記のようにあるみたいです。

主にメモリーリークの対策に必要なメソッドと言われているらしいです。

removeEventListenerについて

window.onloadのようにページ読み込みに1度だけ実行するようなものであれば、 「ハンドラを監視するためのメモリ」を解放することで 厳密にはリークしているわけではありませんが、全体の消費メモリの削減になります。 また、オブジェクトがドキュメントから削除される場合。(これがメモリリークの主な原因です。) ...

それでは後から出てくるのかどうかみてみます。

途中から出てきましたね。

これでは全然かっこよくないので、さらにアニメーションを加えます。

アニメーションの追加

アニメーションは上からフワッと出てくる感を出したいので、上から出てくるように指定します。

import React, {useState, useEffect} from 'react'
import { menuData } from '../data/MenuData';
import { Link } from 'gatsby';
+ import styled,{ keyframes } from 'styled-components';
//アニメーションで使うkeyframes

const ToppageNavbar = () => {
  const [navbar, setNavbar] = useState(false)
  

  useEffect(() => {
    const scrollNav = () => {
      if (window.scrollY >= 780) {
        setNavbar(true);
      }else{
        setNavbar(false);
      }
    };
    scrollNav()
    window.addEventListener("scroll", scrollNav)

    return () => {
      window.removeEventListener('scroll', scrollNav);
    };


  }, [])
  return (
    <Nav active = {navbar} >
      <NavContainer>
        <NavMenu>
          <NavItem>
            {menuData.map((items, index) => (
              <NavLinks to={items.link} key={index}>
                {items.title}
              </NavLinks>
            ))}
          </NavItem>
        </NavMenu>
      </NavContainer>
    </Nav>
  );
};

export default ToppageNavbar;

+ const SlideIn = keyframes`
  0% {
    opacity: 0;
    transform: translateY(-70px);
 //上方向からフワッと出現する
  }
  100% {
    opacity: 1;
    transform: translateY(0);
`
  
const Nav = styled.nav`
  background-color: #fff;
  display: flex;
  justify-content: flex-start;
  align-items: center;
  font-size: 1rem;
  position: sticky;
  top: 0;
  z-index: 999;
   display: ${({ active }) => (active ? "flex" : "none")};
 + animation: ${SlideIn} 0.8s ease-out ;
//styled-componentsのアニメーションの時はアニメーション名を${}で囲むようにする
`

styled-componentsでもkeyframesは使えるので、インポートしてから使います。

styled-componentsでのkeyframesについては下記のサイトでも記述されていますが、基本的に使い方はCSSと変わりません。

Adding CSS Animations with Styled Components

I love using styled-components in a React project. The ability to write CSS right in the component file is so simple and straightforward, and the increased performance of loading only the necessary code for rendered components is great.

こんな感じでできているかみてみましょう。

これで完成ですね。

最後まで読んでいただきありがとうございました。

-PROGRAMMING

Copyright © Iseblog ,@2020 All Rights Reserved.