joppot

コピペで絶対動く。説明を妥協しない

プログラミング

react-modalの背面のスクロールを固定する

投稿日:


概要

みなさんこんにちはcandleです。今回はreact-modalの背面がスクロールした時に動いてしまう問題を解決してみたいと思います。

前提

  1. reactの知識がある

完成版のサンプルコード

サンプルコードを実際に動かしたい場合は以下の2つのライブラリをインストールしてください。
fakerはダミーデータ生成のためにインストールしています。

yarn add faker react-modal

先に完成版のサンプルコードを記述しておきます。これはsrc/App.jsに記述しています。

import React, { Component } from 'react'
import Faker from 'faker'
import Modal from 'react-modal'

Modal.setAppElement('#root')

class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      users: [],
      user: {
        products: [],
      },
      modalIsOpen: false,
    }
  }

  componentWillMount() {
    for (let i = 0; i < 10; i++) {
      let products = []

      for (let j = 0; j < 6; j++) {
        const product = {
          name: Faker.commerce.productName(),
          price: Faker.commerce.price(),
          image: Faker.image.food(30, 40),
        }
        products = [...products, product]
      }

      const user = {
        name: Faker.internet.userName(),
        email: Faker.internet.email(),
        avatar: Faker.internet.avatar(),
        products: products,
      }
      this.setState(prevState => ({
        users: [...prevState.users, user],
      }))
    }
  }

  openModal(user) {
    this.setState({
      user: user,
      modalIsOpen: true,
    })
    document.body.setAttribute('style', 'overflow: hidden;')
  }

  closeModal() {
    this.setState({ modalIsOpen: false })
    document.body.removeAttribute('style', 'overflow: hidden;')
  }

  renderProducts(product) {
    return (
      <div style={{ border: 'solid 1px #eee' }}>
        <img src={product.image} alt={product.name} width="50" height="50" />
        <h4>Name: {product.name}</h4>
        <h4>Price: {product.price}</h4>
      </div>
    )
  }

  renderUsers(user) {
    return (
      <div style={{ border: 'solid 1px #eee' }} onClick={this.openModal.bind(this, user)}>
        <img src={user.avatar} alt={user.name} width="50" height="50" />
        <h4>Name: {user.name}</h4>
        <h4>Email: {user.email}</h4>
      </div>
    )
  }

  render() {
    return (
      <div>
        {this.state.users.map(user => this.renderUsers(user))}
        <Modal
          isOpen={this.state.modalIsOpen}
          onRequestClose={this.closeModal.bind(this)}
          style={customStyles}
          contentLabel="Example Modal"
        >
          <h2>
            {this.state.user.name}
            の制作物
          </h2>
          <button onClick={this.closeModal.bind(this)}>Close</button>
          {this.state.user.products.map(product => this.renderProducts(product))}
        </Modal>
      </div>
    )
  }
}

const customStyles = {
  overlay: {
    position: 'fixed',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    backgroundColor: 'rgba(255, 255, 255, 0.75)',
  },
  content: {
    position: 'absolute',
    top: '40px',
    left: '40px',
    right: '40px',
    bottom: '40px',
    border: '1px solid #ccc',
    background: '#fff',
    overflow: 'auto',
    WebkitOverflowScrolling: 'touch',
    borderRadius: '4px',
    outline: 'none',
    padding: '20px',
  },
}

export default App

サーバを起動し、

yarn run start

ブラウザで確認するとこのような画面が表示されます。

モーダルを開いた時に背面が動かないでしょう。

モーダルをcssで固定

固定は簡単で、<body>タグにcssのoverflow hiddenを付与するだけです。

モーダルを開く関数にdocument.body.setAttribute('style', 'overflow: hidden;')を付与します。サンプルコードの場合はopenModal()になります。

  openModal(user) {
    this.setState({
      user: user,
      modalIsOpen: true,
    })
    document.body.setAttribute('style', 'overflow: hidden;')
  }

逆に、モーダルを閉じる時はこのoverflow: hiddenを取り去ります。

モーダルを閉じる関数にはdocument.body.removeAttribute('style', 'overflow: hidden;')を書きましょう。

サンプルコードはこうします。

  closeModal() {
    this.setState({ modalIsOpen: false })
    document.body.removeAttribute('style', 'overflow: hidden;')
  }

これで背面が固定されます。

まとめ

ちょっとしたことでしたが、実はこの方法を見つけるまでに試行錯誤と紆余曲折をしました。
良いReactライフを

スポンサードリンク

「為になったなぁ」と思ったら、シェアお願いします。

-プログラミング
-, , ,

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

railsのscaffoldでremote formを使ってフォームの送信をajax化する

概要 みなさんこんにちはcandleです。 今回はrailsのformをremoteを使ってajaxしたいとおもいます。 正直、解説するまでもなく簡単です。 前提 適当なrailsプロジェクトが存在す …

Mysqlテーブルの照合順序を変更する

概要 みなさんこんにちはcandleです。今回はテーブルの照合順序を変更する方法を行います。 この方法はやっても、mysqlクエリー1行ですみます。早速やりましょう。 テーブルの照合順序を変更する 次 …

cakephp2.5.6をfabric+cuisineを使用してインストールする

概要 みなさんこんにちはcandleです。今回はcakephp2.5.6の環境構築をfabricを使用して、インストールしてみましょう。cakephpはrailsと比べると100倍くらい簡単に環境構築 …

ruby on railsでpdfファイルをダウンロードさせる

概要 みなさんこんにちはcandleです。pdfファイルのダウンロードのやり方を紹介します。 前提 railsの環境が出来ている twitterbootstrap gem を使用した環境で説明して行き …

ruby on rails のckeditor gemの機能ボタンをカスタマイズする

概要 みなさんこんにちはcandleです。今回はruby on rails のckeditor gemのショートカットボタンをカスタマイズして自分が必要な機能のみを表示してみましょう。 前提 cked …


ベンチャー企業のCTOをやってます。大学時代にプログラミングを始め、javaから入門し、C++へて、PHPへと進み、会社ではRailsを使用。自動化が大好きなプログラマー