1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

React + Rails + GraphQL で画像投稿機能をつくる!

Posted at

最初に

最近Reactもさわることが増えたので、学習用に

  • React + Rails + GraphQL

でSPAの個人アプリを作成しています!
そこで、今回は画像投稿機能をつくってみようとおもいます!

使うものについてさらっと説明

  • Ruby on Rails (バックエンド)
  • React(フロントエンド)
  • TypeScript
  • GraphQL
  • Apollo

実装

バックエンド

画像アップロードのため以下のGemを入れる

# Gemfile
gem 'carrierwave'
gem 'carrierwave-base64' 
  • モデルファイルにアップローダーを指定する記述を追加
    • 以下の記述だけでbase64で渡ってきたデータを画像として保存してくれる...!
# Item.rb
class Item < ApplicationRecord
  mount_base64_uploader :image, ItemImageUploader <- これを追加
end

(もしcarrierwaveがわからない方は、調べていただけますと:pray_tone1:

Resolverにて引数で値を受け取って保存

# app/graphql/mutations/create_item.rb
module Mutations
  class CreateItem < Mutations::BaseMutation
    argument :params, InputTypes::Item, required: true <- 引数用のTypeファイル

    field :item, ObjectTypes::Item, null: false

    def resolve(params:)
      item = Item.create!(params.to_h)

      {item: item}

    rescue => e
      GraphQL::ExecutionError.new(e.message)
    end
  end
end

# app/graphql/input_types/item.rb(引数用Typeファイル)
module InputTypes
  class Item < Types::BaseInputObject
    graphql_name 'ItemAttributes'

    argument :image, String, required: false <- 追加
  end
end

フロントエンド

画像選択用のフォームを作る

  • inputタグ追加(type="file"でファイル選択フォームに)
<input
  name="file"
  type="file"
  accept="image/png"
/>
  • 画像選択フォームができる
    スクリーンショット 2023-02-25 19.45.56.png

useStateを使って、選択画像を管理するstateを追加

  import { useState } from "react";
  const [image, setImage] = useState<string | undefined>(undefined)

画像選択時に、↑のimage stateに画像データをセットする関数を追加

readAsDataURLで、画像をbase64(画像を文字列に変換)にしています!
※ GraphQLはJSONでデータを受け渡すためバイナリデータを扱うことができないので、文字列に!

  const onChangeFile = (e: React.ChangeEvent<HTMLInputElement>) => {
    const files = e.target.files
    if (files && files[0]) {
      const reader = new FileReader()
      reader.readAsDataURL(files[0])
      reader.onload = function() {
        var image: any
        image = reader.result;
        setImage(image); <- image stateに画像をセット
      }
    }
  }
  • inputタグで、画像セット時に↑の関数を呼び出して、選択画像をimage stateにセットする
<input
  name="file"
  type="file"
  accept="image/png"
  onChange={onChangeFile} <- 追加
/>
  • 以下のように、image stateを、imgタグのsrcにセットすると選択中の画像が確認できるかとおもいます!
<img src={image} />

スクリーンショット 2023-02-25 19.59.52.png

あとはimageのデータを、Mutationの引数に渡すだけ

const [createItem] = useCreateItemMutation();
createItem({ variables: { params: { image: image } } });

以上が実装の一例となります!
記事を見てくださりありがとございました!!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?