20201016のReactに関する記事は4件です。

slackのリアクションを監視してHasura経由でReact画面をリアルタイムに更新する

Slackのメッセージのリアクションを監視して、ReactのUIにリアルタイムに反映させたい。
スクリーンショット 2020-10-16 17.35.00.png

やることは大きく分けて以下の3つ

  • slackのメッセージにおけるリアクションの監視
  • 対象メッセージのリアクション回数の更新
  • ReactのUIに反映

slackのメッセージにおけるリアクションの監視

slack APIのEvent Subscriptionsを使う。

URLの指定

エンドポイントをここに入力。
今回はFlaskで事前に用意したエンドポイントを利用。
このエンドポイントでslackからjsonを受け取ってHasuraにクエリを投げる。

発火条件の指定

Subscribe to events on behalf of usersで発火条件を指定する。
今回は、リアクションが押された時に発火させたいので、以下の二つを有効にする。

  • reaction_added
  • reaction_removed

これでリアクションがあった時にエンドポイントにjsonが投げられる。

対象メッセージのリアクション回数の更新

Flaskで処理を行う。
今回は、指定のチャンネルのメッセージのリアクションのみ監視したかったため、チャンネル名でフィルターをかける。
次に、受け取ったjsonの中にメッセージのユニークなidが入っているので、これを元にHasuraの方にクエリを投げてリアクション回数を取得する。
その後、reaction_addedかreaction_removedでそのリアクション回数を増減させて最後にmutation。

ReactのUIに反映

apollo-clientを使ったsubscriptionは公式documentに沿えばok。

参考

Setting up GraphQL subscriptions using apollo-client
https://hasura.io/docs/1.0/graphql/core/guides/integrations/apollo-subscriptions.html#write-your-subscription

Create Subscription and Render Result
https://hasura.io/learn/graphql/react/subscriptions/3-create-subscription/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【ReactNative】ReactNavigationの基本をまとめる

はじめに

ReactNativeで画面を遷移させる際に使う React Navigation ですが、様々なpropsが用意されているので、簡単にまとめていきたいと思います。

別の画面を指定して遷移させる

定義されたルートの宛先名を指定することで、任意の画面に遷移させることができます。

sample.js
onPress={() =>
  navigate('定義されたルート名', { sampleParam: '任意の引数' })
}

ひとつ前の画面に戻る

goBack() を用いることで、現在表示している画面のひとつ前に戻ることができます。

sample.js
onPress={() => goBack()} // ひとつ前の画面に遷移

複数個前の画面に戻る

pop() を用いることで、現在表示している画面の複数個前に戻ることができます。

sample.js
onPress={() => navigation.pop(2)} // ふたつ前の画面に遷移

ナビゲーション履歴を初期化して遷移する

reset() を使うことで、ナビゲーション履歴を初期化して遷移することができます。

sample.js
onPress={() => navigation.reset({
  index: 0,
  routes: [{ name: 'Home' }],
})};
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Next.jsのダイナミックルーティングを実装してみた

Next.jsでは、getStaticPaths・getStaticProps・getServerSidePropsといった似た名前の関数が多く違いがわかりづらいですよね...

今回は、その中でも使用頻度の高いgetStaticPaths・getStaticPropsを使用し、ダイナミックルーティングの簡単なサンプルを作成したいと思います。

こちらが今回作成するサンプルの完成形です。
画面収録-2020-10-15-17.32.51.gif
URL:https://nextjs-dynamic.vercel.app/

JSONPlaceholderのAPIサーバーを使用し、記事一覧・記事詳細ページを表示しています。
見ての通り、全てのデータが事前ビルドされているため表示が高速です。

では、実装までの流れについて説明していきます。

1. ダイナミックルート用のファイル作成

まずは、ダイナミックルート用のファイル(記事詳細ページ)を作成します。
Next.jsでは、pages内でファイル名に[]を使用することで自動的にダイナミックルート対象となります。

 /pages/[id].js                               
   ├ http://localhost:3000/1
   ├ http://localhost:3000/2
   └ ...

ダイナミックルート用のファイルでは、getStaticPathsgetStaticPropsの関数が必要です。

getStaticPaths:ビルド時にレンダリングする必要のあるパスのリストを生成する
getStaticProps:ビルド時に静的なファイルを生成し、ページコンポーネントで使用する値を用意する

これらの関数はクライアント側で実行されることはなく、必ずサーバーサイドで実行されます。

以下は作成した記事詳細ページです。

pages/[id].js
import Link from 'next/link'

// post:getStaticPropsから取得したデータ
export default ({ post }) => {
  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
      <Link href="/">
        <a>Back</a>
      </Link>
    </div>
  )
}

export const getStaticPaths = async () => {
  // 外部APIエンドポイントを呼び出しデータ取得
  const res = await fetch("https://jsonplaceholder.typicode.com/posts")
  const posts = await res.json()  

  // 事前ビルドしたいパスを指定
  const paths = posts.map((post) => ({
    params: {
      // ファイル名と合わせる ※文字列指定
      id: post.id.toString(),
    },
  }))
  // paths:事前ビルドするパス対象を指定するパラメータ
  // fallback:事前ビルドしたパス以外にアクセスしたときのパラメータ true:カスタム404Pageを表示 false:404pageを表示
  return { paths, fallback: false }
}

// paramsには上記pathsで指定した値が入る(1postずつ)
export const getStaticProps = async ({ params }) => {  
  // 外部APIエンドポイントを呼び出しデータ取得
  const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}`)
  const post = await res.json()  

  // ページコンポーネントにpropsとしてに渡す
  return {
    props: {
      post
    },
  }
}

画面表示までの流れ

  1. getStaticPathsで、レンダリングする必要のあるパスのリストを生成する
  2. getStaticPropsで、1で生成したパスのリストから1postsずつAPIエンドポイントを呼び出しデータを取得する
  3. ページコンポーネントがgetStaticPropsからデータを受け取り、画面に表示される

実際にURLにアクセスしてみると、表示が切り替わることが確認できるかと思います。

画面収録-2020-10-15-16.30.12.gif

2. 記事一覧ページ作成

次に、それぞれの詳細ページにリンクする記事一覧を作成します。

こちらのページに関しても、getStaticPropsでページコンポーネントで使用する値を事前に用意する必要があります。

以下は作成した記事一覧ページです。

pages/index.js
import Link from 'next/link'

// posts:getStaticPropsで取得したデータを受け取る
const Home = ({ posts }) => {
  return (
    <div>
      <h1>記事一覧</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>
            {/* リンク先を指定 */}
            <Link href={`/${post.id}`}>
              <a>{post.title}</a>
            </Link>
          </li>
        ))}
      </ul>
    </div>
  )
}

// ビルド時にデータを取得し静的なファイルを事前に生成
export const getStaticProps = async () => {
  // 全記事データを取得
  const res = await fetch("https://jsonplaceholder.typicode.com/posts")
  const posts = await res.json()  

  // コンポーネントに渡すデータを指定
  return {
    props: {
      posts,
    },
  }
}

export default Home

画面表示までの流れ

  1. getStaticPropsで、画面表示させたいデータを取得する
  2. ページコンポーネントがgetStaticPropsからデータを受け取り、画面に表示される

以上でダイナミックルーティングの実装完了になります!

おわりに

Next.js公式がSSGを推薦していることもあり、今後さらにダイナミックルーティングを使用する機会が増えていきそうですね!

公式チュートリアルでは、実際にブログを作成しながらダイナミックルーティングについて学ぶことができるので、より詳しく知りたいという方はぜひお試し下さい!
Next.js Dynamic Routes

参考資料

Next.js 公式ドキュメント
Next.js 9.3 Released, Improves Static Site Generation
JSONPlaceholder

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VSCode + ESLint + Prettier + React + TypeScript (自分用メモ Fall, 2020)

はじめに

目標

前提

  • Node.jsYarnはインストール済みとします(Yarnを使います)

ESLint, Prettier, TypeScript, React のインストール

プロジェクト・フォルダの作成

bash
$ mkdir qiita && cd $_
$ yarn init -y
yarn init v1.22.10
warning The yes flag has been set. This will automatically answer yes to all questions, which may have security implications.
success Saved package.json
✨  Done in 0.04s.

ESLint と Prettier

bash
$ yarn add -D eslint prettier eslint-config-prettier

TypeScript 関連

bash
$ yarn add -D typescript @typescript-eslint/{parser,eslint-plugin}

React 関連

bash
$ yarn add react react-dom
$ yarn add -D @types/{react,react-dom}
$ yarn add -D eslint-plugin-{react,react-hooks}

tsconfig.json

tsconfig.json
{
  "compilerOptions": {
    "target": "ES2015",
    "module": "ES2015",
    "lib": ["DOM", "ES2015"],
    "jsx": "react",
    "strict": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "baseUrl": ".",
    "paths": {
      "*": ["@types/*"]
    }
  }
}

.eslintrc.json

.eslintrc.json
{
  // 適用する環境
  "env": {
    "es6": true,
    "node": true,
    "browser": true,
    "commonjs": true
  },
  // パーサー
  "parser": "@typescript-eslint/parser",
  // jsx を使います
  "parserOptions": {
    "ecmaVersion": 2018,
    "ecmaFeatures": {
      "jsx": true
    },
    "sourceType": "module"
  },
  // React のバージョンは自動検出に
  "settings": {
    "react": {
      "version": "detect"
    }
  },
  "plugins": ["react-hooks", "react", "@typescript-eslint"],
  // 基本的にルールは recommended に従う
  // prettier 関連は配列の最後尾に書く
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:react/recommended",
    "plugin:react-hooks/recommended",
    "prettier",
    "prettier/react",
    "prettier/@typescript-eslint"
  ],
  "rules": {
    // TypeScirpt なので prop-types は要らない
    "react/prop-types": "off"
  },
  // .js ファイルをオーバーライド (webpack.conig.jsなど)
  "overrides": [
    {
      "files": ["*.js"],
      "rules": {
        "@typescript-eslint/no-var-requires": "off",
        "@typescript-eslint/explicit-function-return-type": "off"
      }
    }
  ]
}

注意点: extends では prettier 関連を配列の最後部に記述すること!

.prettierrc.json

prettierのオプションはこちら(少ない!)。

.prettierrc.json
{
  "singleQuote": true,
  "jsxBracketSameLine": true
}

VSCodeの設定

ESLint, Prettier 拡張をインストール

.vscode/settings.json

settings.json
{
  "editor.formatOnSave": true,    // <-- prettierで整形
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true  // <-- eslintでリント
  },
  // デフォルトフォーマッタをprettierに
  "editor.defaultFormatter": "esbenp.prettier-vscode"
}

editor.defaultFormatter がキモ?
editor.formatOnSave でPrettierの整形が効かない時は大抵これを忘れてます。

謝々

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む