- 投稿日:2021-01-10T23:31:14+09:00
React RouterでPrivate RouteをTSで実装する
React RouterのPrivate Route公式サンプルをTypeScriptで記述したバージョンです。
一部は直感的に行かず、React RouterのAPIの構造等を把握する必要がありました。
App.tsximport React, { useContext, createContext, useState } from 'react'; import './App.css'; import { BrowserRouter as Router, Switch, Route, Link, Redirect, useHistory, useLocation, RouteProps, } from 'react-router-dom'; // This example has 3 pages: a public page, a protected // page, and a login screen. In order to see the protected // page, you must first login. Pretty standard stuff. // // First, visit the public page. Then, visit the protected // page. You're not yet logged in, so you are redirected // to the login page. After you login, you are redirected // back to the protected page. // // Notice the URL change each time. If you click the back // button at this point, would you expect to go back to the // login page? No! You're already logged in. Try it out, // and you'll see you go back to the page you visited // just *before* logging in, the public page. export default function App() { return ( <ProvideAuth> <Router> <div> <AuthButton /> <ul> <li> <Link to="/public">Public Page</Link> </li> <li> <Link to="/protected">Protected Page</Link> </li> </ul> <Switch> <Route path="/public"> <PublicPage /> </Route> <Route path="/login"> <LoginPage /> </Route> <PrivateRoute path="/protected"> <ProtectedPage /> </PrivateRoute> </Switch> </div> </Router> </ProvideAuth> ); } const fakeAuth = { isAuthenticated: false, signin(cb: () => void) { fakeAuth.isAuthenticated = true; setTimeout(cb, 100); // fake async }, signout(cb: () => void) { fakeAuth.isAuthenticated = false; setTimeout(cb, 100); }, }; /** For more details on * `authContext`, `ProvideAuth`, `useAuth` and `useProvideAuth` * refer to: https://usehooks.com/useAuth/ */ type DefaultAuth = { user: string | null; signin: ((cb: () => void) => void) | null; signout: ((cb: () => void) => void) | null; }; const defaultAuth = { user: null, signin: null, signout: null }; const authContext = createContext<DefaultAuth>(defaultAuth); function ProvideAuth({ children }: { children: React.ReactNode }) { const auth = useProvideAuth(); return <authContext.Provider value={auth}>{children}</authContext.Provider>; } function useAuth() { return useContext(authContext); } function useProvideAuth() { const [user, setUser] = useState<string | null>(null); const signin = (cb: () => void) => { return fakeAuth.signin(() => { setUser('user'); cb(); }); }; const signout = (cb: () => void) => { return fakeAuth.signout(() => { setUser(null); cb(); }); }; return { user, signin, signout, }; } function AuthButton() { let history = useHistory(); let auth = useAuth(); return auth.user ? ( <p> Welcome!{' '} <button onClick={() => { if (!auth.signout) return; auth.signout(() => history.push('/')); }} > Sign out </button> </p> ) : ( <p>You are not logged in.</p> ); } // A wrapper for <Route> that redirects to the login // screen if you're not yet authenticated. function PrivateRoute({ children, ...rest }: RouteProps & { children: React.ReactNode }) { let auth = useAuth(); return ( <Route {...rest} render={({ location }) => auth.user ? children : <Redirect to={{ pathname: '/login', state: { from: location } }} /> } /> ); } function PublicPage() { return <h3>Public</h3>; } function ProtectedPage() { return <h3>Protected</h3>; } type State = { from: { pathname: string; search: string; hash: string; state: string | null; key: string; }; }; function LoginPage() { let history = useHistory(); let location = useLocation(); let auth = useAuth(); let { from } = (location.state as State) || { from: { pathname: '/' } }; let login = () => { if (!auth.signin) return; auth.signin(() => { history.replace(from); }); }; return ( <div> <p>You must log in to view the page at {from.pathname}</p> <button onClick={login}>Log in</button> </div> ); }
- 投稿日:2021-01-10T22:55:04+09:00
【2021年】React / TypeScript使用のためのDocker + Vagrant環境を構築する
目的
下記の技術を使ったフロントのコンポーネントの作成を行うための環境構築を行いました。
- React
- TypeScript
目的は上記の利用ですが、本記事としてはReact/TypeScriptを触れることはありませんので、Node.jsを利用する環境の構築には利用が可能かと思います。
DockerだけでなくVagrantを採用している理由としては、自分の開発環境がmacであり、
参考記事に記載の理由で動作が遅いことを解消するためです。参考記事
DXを大幅に低下させるDocker for Macを捨ててMac最速のDocker環境を手に入れる
前準備/筆者の環境
参考記事に記載のVagrantやMutagenのインストールが必要です。
筆者の環境としては下記となります。
- MacOS 11.1
- Vagrant 2.2.7
- Mutagen 0.11.8
作成するもの
下記の4つのファイルを作成します。
それぞれのファイルは同一のディレクトリの配置でOKです。
- Vagrantfile
- mutagen.yml
- Dockerfile
- docker-compose.yml
起動をする際にはvagrantから立ち上げて、仮想マシンの中にsshしてdockerの立ち上げとなります。
Vagrantfile
作成する仮想マシンの構成の記載がされているファイルです。
Vagrant.configure('2') do |config| config.vm.box = 'ubuntu/focal64' config.vm.hostname = 'frontcomponent' config.vm.network :private_network, ip: '192.168.60.10' config.vm.network 'forwarded_port', guest: 8000, host: 8000 config.vm.provider :virtualbox do |vb| vb.gui = false vb.cpus = 2 vb.memory = 4096 vb.customize ['modifyvm', :id, '--natdnsproxy1', 'off'] vb.customize ['modifyvm', :id, '--natdnshostresolver1', 'off'] end config.disksize.size = '15GB' config.mutagen.orchestrate = true config.vm.synced_folder './', '/home/vagrant/front_component', type: "rsync", rsync_auto: true, rsync__exclude: ['.git/', 'log/', 'tmp/'] config.vm.provision 'shell', inline: <<-SHELL echo "fs.inotify.max_user_watches = 65536" >> /etc/sysctl.conf && sysctl -p curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh usermod -aG docker vagrant # dockerを更新する場合にはverを調整すること curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose SHELL endportの設定は今後に自分が利用する環境に合わせて設定しています。
あと、vm.provider
などスペックの設定に関しては利用しているPCなどでチューニングすると良いかと思います。他には自分がこれまでにハマったポイントや参考記事を拝見した後に追加した点としては下記となります。利用する場合には注意してください。
hostname
"_"の利用ができないようです。
サービス名などを入れた場合に間違えやすいので注意が必要です。fs.inotify.max_user_watches
node_modulesなど外部のファイルを引いてくるディレクトリが存在する場合にファイル数が多くなりすぎて、エラーとなることがあります。その場合にはファイルのマウントから除外する方が正しいかとは思いますが、typescriptの方定義ファイルなどローカル上にマウントされてないとコード編集時にnode_modules内の型定義ファイルが見つからず加えました。
良い知見をお持ちの方がいたら意見を伺いたいですmutagen.yml
sync: app: mode: "two-way-resolved" alpha: "./" beta: "frontcomponent:/home/vagrant/front_component" ignore: vcs: true paths: - "/log" - "/tmp"vagrantとのファイル同期にmutagenを利用します。
詳細に関しては記事にまとめるほどには理解が追いついていませんので、参考記事を参照していただけると良いかと思います。Dockerfile
Docker Hubに置いてあるDockerのイメージファイルをベースとして、
今回利用するコンテナのベースイメージを作成します。FROM node:15.5.1 ENV LANG C.UTF-8 ENV WORKSPACE=/var/www/front_component/ RUN curl -sL https://deb.nodesource.com/setup_15.x | bash - RUN apt install -y less build-essential nodejs RUN apt install -y vim less RUN npm install n -g RUN n 14.15.4 WORKDIR $WORKSPACEDocker Hubに置いてあるイメージを元に、今回の環境構築用のベースイメージを作成します。
今回は、今後にreact/typescriptを入れていくことを想定しているのでnodeのイメージをして、npmのインストールをしています。docker-compose.yml
version: '3.7' services: front: build: . image: front:1.0 container_name: front tty: true stdin_open: true ports: - "8000:8000" environment: {} volumes: - .:/var/www/front_component # command: "bash -c 'npm i && npm run watch'"コンテナ作成用の設定になります。
コメントアウト部分は今後にreact/typescriptを入れた後に利用する想定ですが、
ここまでの環境構築では利用をしないのでコメントアウトとしています。vagrantおよびdockerの立ち上げ
立ち上げ方
# 先にcdコマンドで上記で作成したファイルの置いてあるディレクトリに移動する vagrant up # vagrantの立ち上げ vagrant ssh # vagrant内へsshでアクセス cd front_component # vagrantにローカルのファイルをマウントしているディレクトリに移動 docker-compose up -d # dockerの立ち上げ以上で環境の立ち上げ完了です。
上記のコマンドと合わせて、自分がよく使うコマンドを記載しておきます。
簡易的な説明のみなので、ちゃんと使う場合には調べて使ってくださいvagrant系
vagrant up # vagrantの立ち上げ vagrant ssh # 立ち上げたvagrantにsshアクセスする vagrant halt # vagrantの終了 vagrant destroy # vagrantで作成した仮装イメージごと削除docker系
docker ps # 起動中のdockerのimageを確認する docker exec -ti <コンテナ名> /bin/bash # コンテナの中にssh的にアクセスする docker attach <コンテナ名> # コンテナで起動中のプロセスを表示する docker logs <コンテナ名> # 強制終了したコンテナの終了時のログなどを見るのに利用する
初投稿ε('∞'*)フゥー
- 投稿日:2021-01-10T21:13:30+09:00
[React] やっぱりReduxもMobXも気に入らないのでVueのVuexを参考に状態管理ライブラリを自作してみた
はじめに
アウトプットをこちらに載せておきます
よろしければTwitterを始めたのでフォローとGithubに☆をしてくださると励みになります!
経緯
Reactを始めてまず思ったのが状態管理ライブラリ多すぎ、非同期するのに追加のミドルウェアもいるの??
という印象でした。Vueの場合はほとんどの場合Vuexを選択することになるし、TypeScriptとの相性は悪いものの、Vuexは非同期を前提としているのでそれだけで完結できるので余計な気はあまり使わないような気がします。
Reactの場合はどうでしょう?
まず事実上のデファクトスタンダードのReduxをはじめとして、Flux、Mobx、Recoilなど、無数に存在します。
非同期をするなら、redux-saga、redux-thunkなどこれまたミドルウェアもたくさん存在します。Vuexと比べたReduxの印象は「記述量多すぎてめんどくさい」、「余計な記述が増えてかえって可読性悪くならないか?」という印象でした。TypeScriptとの相性も良くないし、switch文で分岐するのもなんだかなーという感じ。
Redux ToolkotやRecoilを使えば上記のデメリットを解消できますが、私はオブジェクト指向やDIを多用するので引っかかるものは感じていました。そこで次の選択肢として、MobXが上がりました。MobXはオブジェクト指向をサポートし、まさに魔法のようにリアクティブを実現してくれます。
ルールの強要もほとんどないので本当に自由に実装できます。
最初はこれだ!と思ってうれしく使ってました。
ただ、これはこれでブラックボックスを作りやすくなるので、デバッグがしにくかったり複数人で利用すると秩序が保たれない可能性が出てきます。(本当にわがままなやつですよね)要するに、オブジェクト指向で、記述が楽で、かっちりしたルールのある状態管理ライブラリが欲しいんです!
→じゃあ自作するかという流れでした。そんなこんなで、VuexやElmの良い部分を取り込んで単一方向データフローでオブジェクト指向で記述できる状態管理ライブラリを作成しました。
規模がそこそこ小さい場合や、迅速に単一データフローのアプリを作りたい場合は自分でも積極的に使っていきたいです。成果物の紹介
早速ですが紹介します。
ライブラリのルール
- 状態は常に読み取り専用にしましょう
- 状態を変更するにはActionをDispatchしましょう
- ディスパッチされたActionを処理するすべてのMutationは、Actionに期待される変更と組み合わされた古い状態を反映する新しい状態を作成します
- UIは新しい状態を使用して表示をレンダリングします
※ここでのActionの概念はVuexを参考にしたためReduxとは少し違います
実装
例としてフィボナッチ数列でカウントアップするカウンタを実装してみます。
インストール
yarn add relux.js react-reluxまたは
npm install --save relux.js react-reluxまずは管理したい状態の型を作成
export interface FibState { n: number; count: number; }フィボナッチ数を生成するクラスを作成
export class FibonacciService { public fib(n: number) { if (n < 3) return 1; return this.fib(n - 1) + this.fib(n - 2); } }状態を更新するためのActionを作成
Actionを作成するには
Action<TState, Tpayload>
クラスを継承する必要があります. クラス名がアクション名となります. TStateには状態の型, TPayoadにはペーロードの型を指定してください。 ActionをDispatchした際、invokeメソッドがコールされます.クラス名がアクション名となりますが, Webpackや静的サイトジェネレータなどで圧縮されて元のクラス名がわからなくなる場合は, name プロパティを定義することでアクション名を上書きできます.
import { Action, Feature } from "relux.js" import { FibState } from "./FibState"; import { FibonacciService } from "./FibonacciService"; export class IncrementalFibonacciAction extends Action<FibState, undefined> { // コンストラクタ引数の定義 // デコレーターが使える場合はクラスに@Injectableデコレーターを付与するとこのプロパティを定義しなくても自動で解決される static parameters = [FibonacciService]; name = "IncrementalFibonacciAction "; constructor(private readonly fibService: FibonacciService) { super(); } public invoke(_: undefined): Feature<FibState> { return async ({ dispatch, mutate, state }) => { if (state.n < 40 === false) { return; } // ここで非同期処理も可能 await new Promise(resolve => setTimeout(resolve, 1000)); const fib = this.fibService.fib(state.n + 1); // ここで状態を更新する mutate(s => ({ ...s, count: fib, n: s.n + 1 })); }; } }Storeインスタンスの作成
1つの状態ツリーを機能ごとに複数に分割することができます。複数のアクションと1つの状態の組み合わせは、スライスと呼ばれます。
import { createStore } from "relux.js"; import { IncrementalFibonacciAction } from "./IncrementalFibonacciAction"; import { FibonacciService } from "./FibonacciService"; export const store = createStore({ slices: { counter: { ... }, fib: { name: "fib", actions: [ // 先ほど定義したAction IncrementalFibonacciAction, ], // 初期値 state: { n: 0, count: 0 } } }, // DIするサービスを登録 services: [ // フィボナッチ数を生成するクラス FibonacciService ] }); // slice.stateの型を集約して1つの状態ツリーの型を生成します export type RootState = ReturnType<typeof store.getState>;React Component
useObserverでほしい状態を取り出して、useDispatchの戻り値を利用してActionをDispatchしています。
import { Provider, useDispatch, useObserver } from "react-relux"; import { store, RootState } from "./store"; import { IncrementalFibonacciAction} from "./IncrementalFibonacciAction"; export default () => { return ( <Provider store={store}> <FibCounter /> </Provider> ); }; function FibCounter() { const dispatch= useDispatch(); const counter = useObserver((s: RootState) => s.fib); function increment() { dispatch(IncrementalFibonacciAction, undefined) } return ( <div> <h1>Fibonacci counter</h1> <button onClick={increment}>Compute</button> <p>Compute Fibonacci number when N {"<"} 40</p> <div>Fib: {counter.count}</div> <div>N: {counter.n}</div> </div> ); }おわりに
もしも気に入れば、使っていただけたらなと思います!
- 投稿日:2021-01-10T21:13:30+09:00
[React] ReduxもMobXも合わなかったのでVueのVuexを参考に状態管理ライブラリを自作してみた
はじめに
アウトプットをこちらに載せておきます
よろしければTwitterを始めたのでフォローとGithubに☆をしてくださると励みになります!
経緯
Reactを始めてまず思ったのが状態管理ライブラリ多すぎ、非同期するのに追加のミドルウェアもいるの??
という印象でした。Vueの場合はほとんどの場合Vuexを選択することになるし、TypeScriptとの相性は悪いものの、Vuexは非同期を前提としているのでそれだけで完結できるので余計な気はあまり使わないような気がします。
Reactの場合はどうでしょう?
まず事実上のデファクトスタンダードのReduxをはじめとして、Flux、Mobx、Recoilなど、無数に存在します。
非同期をするなら、redux-saga、redux-thunkなどこれまたミドルウェアもたくさん存在します。Vuexと比べたReduxの印象は「記述量多すぎてめんどくさい」、「余計な記述が増えてかえって可読性悪くならないか?」という印象でした。TypeScriptとの相性も良くないし、switch文で分岐するのもなんだかなーという感じ。
Redux ToolkotやRecoilを使えば上記のデメリットを解消できますが、私はオブジェクト指向やDIを多用するので引っかかるものは感じていました。そこで次の選択肢として、MobXが上がりました。MobXはオブジェクト指向をサポートし、まさに魔法のようにリアクティブを実現してくれます。
ルールの強要もほとんどないので本当に自由に実装できます。
最初はこれだ!と思ってうれしく使ってました。
ただ、これはこれでブラックボックスを作りやすくなるので、デバッグがしにくかったり複数人で利用すると秩序が保たれない可能性が出てきます。(本当にわがままなやつですよね)要するに、オブジェクト指向で、記述が楽で、かっちりしたルールのある状態管理ライブラリが欲しいんです!
→じゃあ自作するかという流れでした。そんなこんなで、VuexやElmの良い部分を取り込んで単一方向データフローでオブジェクト指向で記述できる状態管理ライブラリを作成しました。
規模がそこそこ小さい場合や、迅速に単一データフローのアプリを作りたい場合は自分でも積極的に使っていきたいです。成果物の紹介
早速ですが紹介します。
ライブラリのルール
- 状態は常に読み取り専用にしましょう
- 状態を変更するにはActionをDispatchしましょう
- ディスパッチされたActionを処理するすべてのMutationは、Actionに期待される変更と組み合わされた古い状態を反映する新しい状態を作成します
- UIは新しい状態を使用して表示をレンダリングします
※ここでのActionの概念はVuexを参考にしたためReduxとは少し違います
実装
例としてフィボナッチ数列でカウントアップするカウンタを実装してみます。
インストール
yarn add relux.js react-reluxまたは
npm install --save relux.js react-reluxまずは管理したい状態の型を作成
export interface FibState { n: number; count: number; }フィボナッチ数を生成するクラスを作成
export class FibonacciService { public fib(n: number) { if (n < 3) return 1; return this.fib(n - 1) + this.fib(n - 2); } }状態を更新するためのActionを作成
Actionを作成するには
Action<TState, Tpayload>
クラスを継承する必要があります. クラス名がアクション名となります. TStateには状態の型, TPayoadにはペーロードの型を指定してください。 ActionをDispatchした際、invokeメソッドがコールされます.クラス名がアクション名となりますが, Webpackや静的サイトジェネレータなどで圧縮されて元のクラス名がわからなくなる場合は, name プロパティを定義することでアクション名を上書きできます.
import { Action, Feature } from "relux.js" import { FibState } from "./FibState"; import { FibonacciService } from "./FibonacciService"; export class IncrementalFibonacciAction extends Action<FibState, undefined> { // コンストラクタ引数の定義 // デコレーターが使える場合はクラスに@Injectableデコレーターを付与するとこのプロパティを定義しなくても自動で解決される static parameters = [FibonacciService]; name = "IncrementalFibonacciAction "; constructor(private readonly fibService: FibonacciService) { super(); } public invoke(_: undefined): Feature<FibState> { return async ({ dispatch, mutate, state }) => { if (state.n < 40 === false) { return; } // ここで非同期処理も可能 await new Promise(resolve => setTimeout(resolve, 1000)); const fib = this.fibService.fib(state.n + 1); // ここで状態を更新する mutate(s => ({ ...s, count: fib, n: s.n + 1 })); }; } }Storeインスタンスの作成
1つの状態ツリーを機能ごとに複数に分割することができます。複数のアクションと1つの状態の組み合わせは、スライスと呼ばれます。
import { createStore } from "relux.js"; import { IncrementalFibonacciAction } from "./IncrementalFibonacciAction"; import { FibonacciService } from "./FibonacciService"; export const store = createStore({ slices: { counter: { ... }, fib: { name: "fib", actions: [ // 先ほど定義したAction IncrementalFibonacciAction, ], // 初期値 state: { n: 0, count: 0 } } }, // DIするサービスを登録 services: [ // フィボナッチ数を生成するクラス FibonacciService ] }); // slice.stateの型を集約して1つの状態ツリーの型を生成します export type RootState = ReturnType<typeof store.getState>;React Component
useObserverでほしい状態を取り出して、useDispatchの戻り値を利用してActionをDispatchしています。
import { Provider, useDispatch, useObserver } from "react-relux"; import { store, RootState } from "./store"; import { IncrementalFibonacciAction} from "./IncrementalFibonacciAction"; export default () => { return ( <Provider store={store}> <FibCounter /> </Provider> ); }; function FibCounter() { const dispatch= useDispatch(); const counter = useObserver((s: RootState) => s.fib); function increment() { dispatch(IncrementalFibonacciAction, undefined) } return ( <div> <h1>Fibonacci counter</h1> <button onClick={increment}>Compute</button> <p>Compute Fibonacci number when N {"<"} 40</p> <div>Fib: {counter.count}</div> <div>N: {counter.n}</div> </div> ); }おわりに
もしも気に入れば、使っていただけたらなと思います!
- 投稿日:2021-01-10T21:13:30+09:00
[React] ReduxもMobXも合わなかったので状態管理ライブラリを自作してみた話
はじめに
Reactを始めて数か月ですが、状態管理ライブラリの選定に血迷ってしまって、結局自作したというはなしです。
アウトプットをこちらに載せておきます!
よろしければ、Twitterを始めたのでフォローと、Githubに☆をしてくださると励みになります!
背景
Reactを始めてまず思ったのが状態管理ライブラリ多すぎ、非同期するのに追加のミドルウェアもいるの??
という印象でした。Vueの場合はほとんどの場合Vuexを選択することになるし、TypeScriptとの相性は悪いものの、Vuexは非同期を前提としているのでそれだけで完結できるので余計な気はあまり使わないような気がします。
Reactの場合はどうでしょう?
まず事実上のデファクトスタンダードのReduxをはじめとして、Flux、Mobx、Recoilなど、無数に存在します。
非同期をするなら、redux-saga、redux-thunkなどこれまたミドルウェアもたくさん存在します。Vuexと比べたReduxの印象は「記述量多すぎてめんどくさい」、「余計な記述が増えてかえって可読性悪くならないか?」という印象でした。TypeScriptとの相性も良くないし、switch文で分岐するのもなんだかなーという感じ。
Redux ToolkotやRecoilを使えば上記のデメリットを解消できますが、私はオブジェクト指向やDIを多用するので引っかかるものは感じていました。そこで次の選択肢として、MobXが上がりました。MobXはオブジェクト指向をサポートし、まさに魔法のようにリアクティブを実現してくれます。
ルールの強要もほとんどないので本当に自由に実装できます。
最初はこれだ!と思ってうれしく使ってました。
ただ、これはこれでブラックボックスを作りやすくなるので、デバッグがしにくかったり複数人で利用すると秩序が保たれない可能性が出てきます。(本当にわがままなやつですよね)要するに、オブジェクト指向で、記述が楽で、かっちりしたルールのある状態管理ライブラリが欲しいんです!
→じゃあ自作するかという流れでした。そんなこんなで、VuexやElmの良い部分を取り込んで単一方向データフローでオブジェクト指向で記述できる状態管理ライブラリを作成しました。
規模がそこそこ小さい場合や、迅速に単一データフローのアプリを作りたい場合は自分でも積極的に使っていきたいです。成果物の紹介
早速ですが紹介します。
ライブラリのルール
- 状態は常に読み取り専用にしましょう
- 状態を変更するにはActionをDispatchしましょう
- ディスパッチされたActionを処理するすべてのMutationは、Actionに期待される変更と組み合わされた古い状態を反映する新しい状態を作成します
- UIは新しい状態を使用して表示をレンダリングします
※ここでのActionの概念はVuexを参考にしたためReduxとは少し違います
実装
例としてフィボナッチ数列でカウントアップするカウンタを実装してみます。
インストール
yarn add relux.js react-reluxまたは
npm install --save relux.js react-reluxまずは管理したい状態の型を作成
export interface FibState { n: number; count: number; }フィボナッチ数を生成するクラスを作成
export class FibonacciService { public fib(n: number) { if (n < 3) return 1; return this.fib(n - 1) + this.fib(n - 2); } }状態を更新するためのActionを作成
Actionを作成するには
Action<TState, Tpayload>
クラスを継承する必要があります. クラス名がアクション名となります. TStateには状態の型, TPayoadにはペーロードの型を指定してください。 ActionをDispatchした際、invokeメソッドがコールされます.クラス名がアクション名となりますが, Webpackや静的サイトジェネレータなどで圧縮されて元のクラス名がわからなくなる場合は, name プロパティを定義することでアクション名を上書きできます.
import { Action, Feature } from "relux.js" import { FibState } from "./FibState"; import { FibonacciService } from "./FibonacciService"; export class IncrementalFibonacciAction extends Action<FibState, undefined> { // コンストラクタ引数の定義 // デコレーターが使える場合はクラスに@Injectableデコレーターを付与するとこのプロパティを定義しなくても自動で解決される static parameters = [FibonacciService]; name = "IncrementalFibonacciAction "; constructor(private readonly fibService: FibonacciService) { super(); } public invoke(_: undefined): Feature<FibState> { return async ({ dispatch, mutate, state }) => { if (state.n < 40 === false) { return; } // ここで非同期処理も可能 await new Promise(resolve => setTimeout(resolve, 1000)); const fib = this.fibService.fib(state.n + 1); // ここで状態を更新する mutate(s => ({ ...s, count: fib, n: s.n + 1 })); }; } }Storeインスタンスの作成
1つの状態ツリーを機能ごとに複数に分割することができます。複数のアクションと1つの状態の組み合わせは、スライスと呼ばれます。
import { createStore } from "relux.js"; import { IncrementalFibonacciAction } from "./IncrementalFibonacciAction"; import { FibonacciService } from "./FibonacciService"; export const store = createStore({ slices: { counter: { ... }, fib: { name: "fib", actions: [ // 先ほど定義したAction IncrementalFibonacciAction, ], // 初期値 state: { n: 0, count: 0 } } }, // DIするサービスを登録 services: [ // フィボナッチ数を生成するクラス FibonacciService ] }); // slice.stateの型を集約して1つの状態ツリーの型を生成します export type RootState = ReturnType<typeof store.getState>;React Component
useObserverでほしい状態を取り出して、useDispatchの戻り値を利用してActionをDispatchしています。
import { Provider, useDispatch, useObserver } from "react-relux"; import { store, RootState } from "./store"; import { IncrementalFibonacciAction} from "./IncrementalFibonacciAction"; export default () => { return ( <Provider store={store}> <FibCounter /> </Provider> ); }; function FibCounter() { const dispatch= useDispatch(); const counter = useObserver((s: RootState) => s.fib); function increment() { dispatch(IncrementalFibonacciAction, undefined) } return ( <div> <h1>Fibonacci counter</h1> <button onClick={increment}>Compute</button> <p>Compute Fibonacci number when N {"<"} 40</p> <div>Fib: {counter.count}</div> <div>N: {counter.n}</div> </div> ); }おわりに
もしも気に入れば、使っていただけたらなと思います!
- 投稿日:2021-01-10T20:13:22+09:00
Reactでカウントアップ機能を作る
カウントアップ機能を作る
+ボタンを押すと1ずつ数字が増えていくカウントアップ機能をReactでつくる。
stateを定義する
constructor
内でプロパティ名がcount
、値が0
のstate
を定義する。constructor(props) { super(props); this.state = {count:0}; }ボタンとつくり、stateを表示
ボタンは
button
のタグを使ってつくる。そして前述で定義したstate
をreturn
内で表示させる。その際、this.state.count
はJavascriptなので、{}
で囲む。render() { return ( <div> <h1>{this.state.count}</h1> <button>+</button> </div> ); }handleClickを定義
handleClick
のメソッドを定義して、state
のcount
の値に1
を足す処理を追加する。handleClick(){ this.setState({count: this.state.count + 1}); }buttonタグにonClickイベントを追加
button
タグにonClick
のイベントを追加して、onClick
のイベント時に前述で定義したhandleClick
のメソッドが呼び出されるようにする。<button onClick={()=>{ this.handleClick() } }>+</button>最後に
洗練さんでインターン(Progate React)です。
Progate React最後に
現在ここでインターンしています。
まだまだ駆け出しですが頑張ります!やる気は人一倍です!
洗練
- 投稿日:2021-01-10T19:22:12+09:00
Reactでfirebaseのconfig.jsファイルにあるappIdとstorageBucketを隠す方法【備忘録】
初めに
初心者です。
ある日Reactの勉強のためfirebaseを使用し個人をアプリを作成。
知人にレビューしてもらったところappIdとstorageBucketが公開されており隠す必要があると指摘を受けました。
どうやらセキュリティ的にかなりまずいと...公開しないようにするには
ズバリ環境変数を使用して解決しました。
1 .rootディレクトリ直下に.envファイルを作成
root/
├ src/
│ └ firebase/
│ └ config.js/
├ env2 .envファイルの中身を以下のように記述
create react appの公式サイトを見るとReactで環境変数を作る前は
REACT_APP_
を変数の頭に記載する必要があるため変数名1つ1つに加える。.envREACT_APP_apiKey="AAAAAAAAAAAAAAAAAAAA" REACT_APP_authDomain= "BBBBBBBBBBBBBB" REACT_APP_projectId="CCCCCCCCCCCCCCC" REACT_APP_storageBucket="DDDDDDDDDDDDDD" REACT_APP_messagingSenderId="EEEEEEEEEEE" REACT_APP_appId="1:1111111111:web:1111111111111" REACT_APP_measurementId="FFFFFFFFFFFF"3 環境変数を使ってconfig.jsファイルappId等を記述する
他のファイルで環境変数を呼び出す際は変数名の前に
process.env.
を加えてあげればいい.src/firebase/config.jsconst firebaseConfig = { apiKey: process.env.REACT_APP_apiKey, authDomain: process.env.REACT_APP_authDomain, projectId: process.env.REACT_APP_projectId, storageBucket: process.env.REACT_APP_storageBucket, messagingSenderId: process.env.REACT_APP_messagingSenderId, appId: process.env.REACT_APP_appId, measurementId: process.env.REACT_APP_measurementId }; export {firebaseConfig};最後に忘れずに.envファイルを.gitigoreに加えてあげる
.gitignore/node_modules /.pnp .pnp.js /coverage /build # misc .DS_Store .env.local .env.development.local .env.test.local .env.production.local npm-debug.log* yarn-debug.log* yarn-error.log* .envこれでGithubに載せた時に環境変数のおかげでappIdとstorageBucketが公開されないようになりましたね!
参考:Create React App
https://create-react-app.dev/docs/adding-custom-environment-variables/#referencing-environment-variables-in-the-html
- 投稿日:2021-01-10T18:31:59+09:00
Reactの関数コンポーネントの基本をまとめてみた
(まだ、完全にまとまってません、これから追記していきます)
業務でReactを使って1年以上経ちますが、数ヶ月前から新しく作るコンポーネントは関数コンポーネント+TypeScriptに移行しました。
元々はClassコンポーネントで書いていたのですが、なぜ関数コンポーネントが優れているのかを知っておきたかったのと、現場でベテランエンジニアから学んだ書き方のTipsなどを記事にしようと思います。関数コンポーネントとは?
Classに比べると簡潔に見通しよく書けるメリットがあったものの、Classの様にStateを持つ事ができなかった。(当たり前ですが、関数は状態を持つことができません。関数の実行が終われば、関数内の変数はスコープから外れ、アクセスできなくなります、クロージャーとかありますが、、)
そこで考案されたのがフックです。フックは、関数コンポーネントの中からReactの機能へ接続(Hooks into)することを実現しました。フックを用いることで、関数コンポーネントにおいてもクラスコンポーネントとほぼ同等の機能を実現することができる様になったわけです。
これによって、関数コンポーネントが主流になったらしいです。
では、フックとは?
フックは、関数コンポーネントに state やライフサイクルといった React の機能を “接続する (hook into)” ための関数です。フックは React をクラスなしに使うための機能ですので、クラス内では機能しません。今すぐに既存のコンポーネントを書き換えることはお勧めしませんが、新しく書くコンポーネントで使いたければフックを利用し始めることができます。
- React公式ドキュメントから抜粋ですので、私がフロント開発に携わるサービスもClassコンポーネントが残っていて混在してる状態です。
では、基本のフックを見ていきましょう。
・ステートフック useState
その名の通り、state(状態)を持つ事ができる様になります。最も単純なケースで表示、非表示を切り替えるboolean変数(showMenu)を作りましょう。
お作法として変数を書き換えるメソッド名はset + 変数名です。const [showMenu, setShowMenu] = useState<boolean>(false); const toggleVisibility = () => setShowMenu(prev => !prev);
prev => !prev
と書いてるのは、現在の状態 => 現在の状態の逆
という事です。・副作用フック useEffect
Classでいう、ComponentDidMount、ComponentDidUpdateを行う事ができる。
第一引数にcallbackを入れて、第二引数に依存する値の配列を入れる
* 依存する値が変更される度にcallbackが実行されるuseEffect( () => { 実行したい処理 }, [ 依存する値/state ] );・メモ化フック
同じ結果を返す処理に関しては初回のみ処理を実行しておき、2回目以降は前回の処理結果を呼び出すことで毎回同じ処理を実行しなくてよくなります。これはプログラミングではメモ化と呼ばれるテクニックで、それをReact Hooks上で簡単に利用できるのがuseMemoとuseCallbackです。
パフォーマンス向上のためにuseMemo、useCallbackは使われる。
パフォーマンス向上のポイントは 無駄な計算を抑え 、再レンダリングをできるだけ抑える この2つです。useMemoは、計算結果を記憶し、必要な時だけ再計算することができる機能
useCallbackは、子コンポーネントに渡すコールバック関数を記憶しておく事ができる機能ですまとめ
関数コンポーネントのメリットは、constructor, renderなどが不要で記述量を減らせるからこっちでやるべき。
参考
https://www.to-r.net/media/react-tutorial-hooks-usememo-usecallback/
https://times.hrbrain.co.jp/entry/react-hooks-performance
https://sbfl.net/blog/2019/11/12/react-hooks-introduction/
- 投稿日:2021-01-10T17:46:24+09:00
[React] firestoreのデータをaxios取得に書き換える
開発環境
react : 17.0.1
node : 12.18.2
npm : 6.14.5
firebase : 8.2.1
axios : 0.21.1既存コード
今回はusersコレクションをfirestoreで用意しておき、userのデータをfirestoreから取得し、userのnameを一覧で表示させる実装です。
top.jsimport React, { useState, useEffect } from 'react' import firebase from '../lib/firebase' const Top = () => { const [users, setUsers] = useState([]) // firestoreからuserのデータを取得する関数 const getFirestoreUsers = async () => { const snapshot = await firebase.firestore().collection('users').get() const users = snapshot.docs.map(doc => doc.data()) setUsers(users) } useEffect(() => { getFirestoreUsers() }, []) return ( <div> { users.map((user, index) => ( <p key={index}>{user.name}</p> )) } </div> ) export default Topaxiosの導入
yarn add axios
axiosでfirestoreのデータを取得する
userShow.jsimport React, { useState, useEffect } from 'react' import axios from 'axios' const UserShow = () => { const [users, setUsers] = useState([]) useEffect(() => { // プロジェクトIDは環境変数で呼び出す // process.envを付けるのを忘れずに const USERS_URL = `https://firestore.googleapis.com/v1/projects/${process.env.REACT_APP_PROJECT_ID}/databases/(default)/documents/users` const fetchUsersData = async () => { const result = await axios(USERS_URL) setUsers(result.data.documents) } fetchUsersData() }, []) return ( <div> { users.map((user, index) => ( <p key={index}>{user.fields.name.stringValue}</p> )) } </div> ) } export default UserShow※useEffectを少しリファクタリングしました(2021/1/11)
userShow.jsuseEffect(() => { axios.get(USERS_URL) .then(res => res.data.documents) .then(fields => setUsers(fields)) }, [])まとめ
viewで呼び出す記述が長い気がするので、他に良い実装方法があれば教えていただきたいです。。
参考記事
Cloud Firestore REST API を使用する
How to fetch data with React Hooks?
- 投稿日:2021-01-10T16:36:11+09:00
DB 操作まで JS で完結!Next.js × Prisma を CRUD アプリケーションでざっくり理解する。
何について書いた記事か?
- Next.js × Prisma を利用して CRUD アプリケーションを作成した ので、そのまとめ記事です.
- Next.js は React でアプリケーションを作成するためのフレームワークです.
- Prisma は Node.js のための ORM です.
- 各レイヤーの役割とソースコードを対応付けながら説明することで、『
Next.js
×Prisma
で作るとどんな実装になるのか?』 をざっくりと理解することを目指します.- 開発を始める前にこの記事で概要を掴む 的な使い方をしてくれると嬉しいです
こんな人にオススメ
- Next.js / Prisma に興味を持っていて、まずはこれらで実現できることを知りたい.
- React / Vue.js を書いていて、バックエンドも JS (TS) で書けたらいいなと思っている.
注意点
- サンプルアプリケーション開発のハンズオン的な説明は行っていません.
- 実際に手を動かす際には 開発に役立つチュートリアル集 などを参照してください.
- 自分は React, TypeScript の経験が浅いので、慣例 / ベストプラクティスに沿っていないソースがある と思います
- 逆に言えば、慣れていなくても楽しく、ストレスなく開発できました!
- 『ここはこう書いた方がいいよ!』といったご指摘があれば、コメントで教えていただけると嬉しいです
何を作ったか?
シンプルに CRUD できるだけのアプリケーションです.
- 題材は何でもよかったので、スターバックスのカスタマイズドリンクを CRUD する前提にしています.
ちゃんみおスペシャル を登録したかっただけ.
- 認証は入れていないので好きにデータ編集してもらってOKです.
- (不正利用対策は主目的でないので、常識の範囲内で抑えてくれると助かります )
- 性能: ローカル開発では気になりませんでしたが、デプロイすると DB との通信に結構時間がかかるようになってしまった (特に初回通信) ので、Vercel か AWS RDS で追加で設定すべき項目があるかもしれません.
Next.js × Prisma で作ったアプリケーションの構成
新しい技術を学ぶときの難しさの一つに 『色んな登場人物が出てきて関係性がわからない 』 ということがあると思っているので、最初に アプリケーションの主要な構成 を説明しておきます.
ただ、この説明だけでそれぞれについて深く理解することは難しいと思うので、まずは 『なるほど、こういうものがあるのね 』 と把握してもらえれば OK です.
WEB ページにアクセスされてから DB 操作までのフロー
- 図の が開発環境 / が本番環境です.
- 本番での差分にはオレンジの枠線を付けています.
- フロントエンドは React による実装で、UI コンポーネントとして chakra-ui を利用しました.
- バックエンドを Next.js の API Routes で実装しています.
- これにより、フロントエンド / バックエンドがどちらも Next.js 上で実行される ことになります.
- フロントエンド ⇄ バックエンドの通信は axios で行います.
- バックエンド ⇄ DB の通信は Prisma で行います.
CRUD ごとにソースコードを理解する
前置きが長くなってしまいましたが、ようやく Next.js / Prisma のコードに関する説明です.
まずは CRAETE を例に、React コンポーネント ⇄ API Routes ⇄ Prisma
の関連図とソースコード を見ていきます.
READ / UPDATE / DELETE については、Prisma のコード例だけ紹介しておきます.Prisma の基本的な書き方を集中するため、エラーハンドリングは省略しています.
CREATE
CREATE するまでのフロー
CRAETE を行う React コンポーネント
pages/create.tsxexport default function Create() { ... const createBeverage = async (values: BeverageFormData, actions) => { // Formik からフォームに入力された値を取得 const body = { name: values.name, description: values.description, price: Number(values.price), isRecommend: values.isRecommend, }; // axios で API Routes として定義された URL に通信を飛ばす await axios.post("/api/beverages", body); // 登録後のロジック ... };CRAETE を行う API Routes ( Prisma Client を利用 )
pages/api/beverages.tsconst handleCreate = async ( req: NextApiRequest, res: NextApiResponse<Beverage> ) => { // request からフォームの値を取得 const { name, description, price, isRecommend } = req.body; // 登録前のチェック ... // prisma - CREATE // Prisma Client を呼び出して、DB にデータを登録する. const beverage = await prisma.beverage.create({ data: { name, description, price, isRecommend }, }); // 登録結果を JSON で返却する res.json(beverage); };READ
READ を行う API Routes ( Prisma Client を利用 )
pages/api/beverages.tsconst handleRead = async ( req: NextApiRequest, res: NextApiResponse<Beverage[]> ) => { // prisma - READ // テーブル内の全データを id 昇順に取得 const beverages = await prisma.beverage.findMany({ orderBy: { id: "asc", }, // 取得データを絞り込む場合はココに `where` などを追加していく // https://www.prisma.io/docs/concepts/components/prisma-client/crud }); res.json(beverages); };UPDATE
UPDATE / DELETE では、どのデータに対して操作するのかを特定するために、ファイル名を
[id].ts
として URL から情報を受け取っています.
ここでは、Next.js - Dynamic API Routes という仕組みを利用しています.UPDATE を行う API Routes ( Prisma Client を利用 )
pages/api/beverage/[id].tsconst handleUpdate = async ( req: NextApiRequest, res: NextApiResponse<Beverage> ) => { // URL から id を取得 const url = req.url; const updateID = parseInt(url.split(/\//, 10).pop()); // request からフォームの値を取得 const { name, description, price, isRecommend } = req.body; // 更新前のチェック // prisma - UPDATE // id が一致したデータに対して、フォームに入力された値で更新 const beverage = await prisma.beverage.update({ where: { id: updateID }, data: { name, description, price, isRecommend }, }); res.json(beverage); };DELETE
DELETE を行う API Routes ( Prisma Client を利用 )
pages/api/beverage/[id].tsconst handleDelete = async ( req: NextApiRequest, res: NextApiResponse<Beverage> ) => { // URL から id を取得 const url = req.url; const deleteID = parseInt(url.split(/\//, 10).pop()); // prisma - DELETE // id が一致したデータを削除 const beverage = await prisma.beverage.delete({ where: { id: deleteID, }, }); res.json(beverage); };見ていただいた通り、Prisma を利用すると DB 操作が簡単に書けていい ですね!
また、スキーマ定義を元に型定義が生成されるので、タイプセーフに書ける というのも大きなメリットです.
- より詳しい情報は、Prisma - Prisma Client などをチェックしてください.
Next.js × Prisma で開発するメリットは何か?
実際に開発して感じた
Next.js
×Prisma
のメリットについてまとめておきます.メリット : JS (TS) だけで完結するため、キャッチアップコストを抑えられる
- 当然ですが、フロントエンド / バックエンドが同一言語なので開発のキャッチアップコストを抑えることができます.
- また、今回開発した構成だと 従来の REST API と構成が近いため、そういった意味でも理解しやすい のではと思っています.
- React / Vue.js などのモダンフロントエンドに足を突っ込むとそれだけで結構なキャッチアップコストを支払うことになるので、『そこで学んだ技術でバックエンドも書きたい』というのは自然な発想で、それが実現できるという意味で 開発体験は非常によかった です.
メリット : 同一言語 / 同一ディレクトリのため共通化がしやすい
- 全てが JS で書かれることで、これまでフロントエンド / バックエンドで別々に管理されていた仕組みを簡単に共通化できるようになります.
- 例えば、今回のアプリケーションではバリデーション定義を共通化したので、以下に実装例を載せておきます.
バリデーション定義の共通化
BeverageFormSchema.ts
という Yup スキーマを定義して、それをフロントエンド / バックエンドそれぞれからimport
することで簡単にバリデーション定義を共通化することができましたvalidators/BeverageFormSchema.ts// Yup で入力チェックのためのスキーマを定義する export const beverageFormSchema = Yup.object({ name: Yup.string().required(), description: Yup.string(), price: Yup.number().min(0).max(3000), isRecomment: Yup.boolean(), });Frontend
components/BeverageForm.tsx// 1. スキーマをインポートして... import { beverageFormSchema } from "../validators/BeverageFormSchema"; ... export default function BeverageForm({ ... }) { return ( <Formik initialValues={initialValues} onSubmit={onSubmit} // 2. Formik に props として渡す validationSchema={beverageFormSchema} >Backend
pages/api/beverages.ts// 1. スキーマをインポートして... import { beverageFormSchema } from "../../validators/BeverageFormSchema"; ... const handleCreate = async ( ... ) => { const { name, description, price, isRecommend } = req.body; // 2. Yup の API を利用してバリデーションチェック const isValid = await beverageFormSchema.isValid({ name, description, price, isRecommend, }); if (!isValid) { res.status(400).end("sent param is invalid."); return; }メリット : サーバー管理が楽になる
yarn dev
を実行して Next.js の開発用サーバーを立てれば SSR / ISR や API Routes もそこで実行されるため、フロントエンド / バックエンドで別々の開発用サーバーを管理しなくてよくなります.- 個人開発や小規模なアプリにとって、このコンパクトさは大きな魅力 だと思いました.
おわりに
いかがだったでしょうか.
Next.js × Prisma で開発をしてみて感じた良さが少しでも伝わっていれば嬉しいです.この記事で『興味を持ったよ』という方は、是非以下のチュートリアルなどを参考に実際に開発をしてみることをオススメします.
結局、手を動かしてみるのが一番理解できると思うので!以上、長い記事を読んでいただいてありがとうございました
開発に役立つチュートリアル集
- Next.js - Create a Next.js App
- Next.js の公式チュートリアルです.
- Next.js の各機能についてハンズオン形式で解説されていて、図も豊富で非常に分かりやすかった です.
- Prisma - Quickstart
- Prisma を TS と SQLite で試すチュートリアルです.
- Next.js のようなフレームワークと分離して Prisma 単体から理解を始めたい という方にオススメです.
- Prisma - How to Build a Fullstack App with Next.js, Prisma, and PostgreSQL
- つい最近 Prisma の公式ページに追加されていた記事なので自分はこれには沿っていないのですが、上で説明したものと同じ技術要素でのチュートリアルです.
- プロジェクトの作成からデプロイまで丁寧に解説されていた ので、これに沿っていけば一通りの開発は順調に進められそうでした.
- 投稿日:2021-01-10T15:11:11+09:00
【Next.js】next/routerを基礎からしっかり。
前書き
筆者が
Next.js
を仕事で書くことになったので、1から勉強するためにアウトプット記事を書くことにしました。
基本的にはドキュメントを噛み砕いて、翻訳した記事です。間違っているところなどあれば、ご指摘していただけるとありがたいです?♂️以下、本題です。
*前提知識として【Next.js】Routingを基礎からしっかり。を一読しておくと、理解しやすいかと
useRouter
useRouter hook
を使うと、アプリ内のrouter
オブジェクトにアクセスすることができます。import { useRouter } from 'next/router' const Hoge = ({ children, href }) => { const router = useRouter() const handleClick = (e) => { e.preventDefault() route.push(href) } return ( <a href={href} onClick={handleClick}> { children } </a> ) }
Hoge
コンポーネントの子要素をラップして、指定したhref
へのリンクコンポーネントを作成するコードです。
const router = useRouter()
の部分でrouter
オブジェクトを取得できます。具体的にrouter
オブジェクトに定義されているメソッドは下記です。router object
pathname
:String
=> 現在のroute
を表示。/pages
内のpathを表示します。query
:Object
=> オブジェクトにパースされたクエリ文字列を表示します。asPath
:String
=> ブラウザに表示される(クエリを含む)pathを表示します。basePath
:String
=> 使えるBasePath
を表示する。主な関数はこんな感じです。まだいくつかあるので、気になる方は調べてみてください。
router.push
クライアント側の遷移を処理します。このメソッドは
next/link
が苦手な部分をカバーくれます。router.push(url, as, options)
url
:ここに遷移しますas
:ブラウザに表示されるURLのオプションのデコレータoptions
:設定オプション
shallow
:再実行せずに現在のページのパスを更新する使い方
事前に定義されたルート(
pages/about.js
)への遷移import { useRouter } from 'next/router' export default function Page() { const router = useRouter() return <span onClick={() => router.push('/about')}>Click me</span> }動的なルート(
pages/post/[pid].js
)への遷移import { useRouter } from 'next/router' export default function Page() { const router = useRouter() return <span onClick={() => router.push('/post/abc')}>Click me</span> }
pages/login.js
へリダイレクトさせたい場合。認証の後のページに便利。import { useEffect } from 'react' import { useRouter } from 'next/router' const useUser = () => ({ user: null, loading: false }) export default function Page() { const { user, loading } = useUser() const router = useRouter() useEffect(() => { if (!(user || loading)) { router.push('/login') } }, [user, loading]) return <p>Redirecting...</p> }With URL object
URLオブジェクトは
next/link
と同じように使うことができます。URLとパラメータの両方で使用できます。import { useRouter } from 'next/router' export default function ReadMore({ post }) { const router = useRouter() return ( <span onClick={() => { router.push({ pathname: '/post/[pid]', query: { pid: post.id }, }) }} > Click here to read more </span> ) }オブジェクトの形で
pathname
とquery
を指定していることが確認できるかと思います。ここでは動的なルーティングを実現しています。router.replace
router.replace(url, as, options)それぞれの役目は
router.push
と同じです。
next/link
のreplace
のprop
と同様に、URLエントリを履歴スタックに追加するのを防ぎます。わかりにくいので例をみていきましょう。では、使い方を見ていきましょう。
使い方
import { useRouter } from 'next/router' export default function Page() { const router = useRouter() return <span onClick={() => router.replace('/home')}>Click me</span> }router.prefetch
クライアント側の遷移を高速化するためにページをプレフェッチします。とはいえ
next/link
が自動的にページのプリフェッチを行うため、この方法はnext/link
を使用しないナビゲーションにのみ有用です。ちなみに
Production
環境での話であり、開発環境ではプレフェッチしません。使い方
ログインページがあり、ログイン後にダッシュボードにリダイレクトするとします。その場合、次の例のように、ダッシュボードをプリフェッチすることで、より速く遷移させることができます。
つまり
next/link
では自動的にプリフェッチしてくれるのですが、リダイレクト処理等でnext/route
を使う場合はプリフィッチしてあげると表示を高速にしてくれます。import { useCallback, useEffect } from 'react' import { useRouter } from 'next/router' export default function Login() { const router = useRouter() const handleSubmit = useCallback((e) => { e.preventDefault() fetch('/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ /* Form data */ }), }).then((res) => { // Do a fast client-side transition to the already prefetched dashboard page if (res.ok) router.push('/dashboard') }) }, []) useEffect(() => { // Prefetch the dashboard page router.prefetch('/dashboard') }, []) return ( <form onSubmit={handleSubmit}> {/* Form fields */} <button type="submit">Login</button> </form> ) }基本的な使い方は以上です。ではでは〜
- 投稿日:2021-01-10T14:18:48+09:00
【Next.js】Base Pathを基礎からしっかり。
前書き
筆者が
Next.js
を仕事で書くことになったので、1から勉強するためにアウトプット記事を書くことにしました。
基本的にはドキュメントを噛み砕いて、翻訳した記事です。間違っているところなどあれば、ご指摘していただけるとありがたいです?♂️以下、本題です。
Base Path
どんな時に使うの?
Next.js
アプリケーションをドメインのサブパスの下にデプロイするには、basePath設定オプションを使うことができますちょっとわかりにくい。。。噛み砕いて解説してきます。
例えば
example.com/hoge
みたいな感じでデプロイしたい場合、にBasePath
設定をすることで解決してくれるということです。具体的にどう設定するの?
example.com/hoge
でデプロイしたい場合は、next.config.js
を下記のように設定してあげればOKです。next.config.jsmodule.exports = { basePath: '/docs', }Links
他のページにリンクするには、
next/link
やnext/router
を使えばbasePath
を考慮して自動的に変換してくれます。例えばexport default function HomePage() { return ( <> <Link href="/about"> <a>About Page</a> </Link> </> ) }このリンクコンポーネントは実際には下記のように出力されます。
<a href="/hoge/about">About Page</a>ちゃんと
hoge
が追加されていることが確認できると思います。つまり、全てのリンクコンポーネントに対して、basePath
を追加する必要はないということです。便利!以上です。ではでは〜
参考記事
- 投稿日:2021-01-10T11:53:25+09:00
Next.jsで作ったWebアプリをデスクトップアプリ化した
はじめに
公式に例を参考にして、既に作ったWebアプリをデスクトップアプリ化してみました。公式チュートリアルで作ったものを例にして書いていきたいと思います。
とりあえずデスクトップアプリ化するのいう感じで、そのまま機能を全部使えるとは限らず、追加で色々な実装が必要になると思いますが、少しでも役立てたら嬉しいです。今回は下の画像のようにsrcディレクトリにpagesやcomponentsディレクトリが入っている構成でやっていきたいと思います。
作成したリポジトリ:https://github.com/NozomuTsuruta/my-blog
導入
まず、以下のコマンドで必要なpackageをインストールします。
## npm npm install electron-is-dev electron-next npm install --save-dev electron electron-builder ## yarn yarn add electron-is-dev electron-next yarn add -D electron electron-builderElectron用のファイル作成
その後、以下のように
electron-src
に3つのファイルを作成します。electron-nextの型定義ファイル↓
electron-src/electron-next.d.tsdeclare module "electron-next" { interface Directories { production: string; development: string; } export default function ( directories: Directories | string, port?: number ): Promise<void>; }windowを開く、閉じる時の設定や処理↓
electron-src/index.tsimport { join } from "path"; import { format } from "url"; import { BrowserWindow, app, shell } from "electron"; import isDev from "electron-is-dev"; import prepareNext from "electron-next"; app.on("ready", async () => { await prepareNext("."); const mainWindow = new BrowserWindow({ width: 1000, height: 800, webPreferences: { nodeIntegration: false, preload: join(__dirname, "preload.ts"), }, }); mainWindow.webContents.on("new-window", (event, url) => { event.preventDefault(); shell.openExternal(url); }); const url = isDev ? "http://localhost:8000/" : format({ pathname: join(__dirname, "../out/index.html"), protocol: "file:", slashes: true, }); mainWindow.loadURL(url); }); app.on("window-all-closed", app.quit);設定はお好みで↓
electron-src/tsconfig.json{ "compilerOptions": { "allowJs": true, "alwaysStrict": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "isolatedModules": true, "jsx": "preserve", "lib": ["dom", "es2017"], "module": "commonjs", "moduleResolution": "node", "noEmit": false, "noFallthroughCasesInSwitch": true, "noUnusedLocals": true, "noUnusedParameters": true, "resolveJsonModule": true, "skipLibCheck": true, "strict": true, "target": "esnext", "outDir": "../main" }, "exclude": ["node_modules"], "include": ["**/*.ts", "**/*.tsx", "**/*.js"] }package.jsonに追加
MyAppの部分はアプリ名です。
次に
package.json
に以下を追加package.json{ ... "productName": "MyApp" "main": "main/index.js", "scripts": { ... "dev-electron": "tsc -p electron-src && electron .", "dist": "next build && next export && tsc -p electron-src && electron-builder" }, ... }一応アプリアイコンはこんな書き方で変更できます↓
package.json{ ... "build": { "mac": { "icon": "./public/icons/icon.icns", "target": [ "dmg" ] }, "win": { "icon": "./public/icons/icon.ico", "target": "msi" } } }
.gitignore
にmainとdistを追加しておきましょう.gitignore/main /dist作成
最後に以下のコマンドを実行します。Windowsのアプリを作りたい場合は後ろに
--win --x64
をつけます。## npm npm dist ## yarn yarn distFinderなどからdmgファイル(windowsはフォルダーからexeファイル)を開くとインストールできます!
最後に
ここまで読んでいただきありがとうございます!私自身Electronに関しての知識がまだまだ浅いので詳しく説明できなかった部分が多いのでもう少し学習を進めていきたいと思います。少しでもお役に立てれば嬉しいです!
- 投稿日:2021-01-10T08:13:02+09:00
firebaseでメールアドレスを取得する方法
Firebaseでユーザネームをメールアドレスを取得する方法
export const createUserProfileDocument = (userAuth. additionalData) => { if(!userAuth) return; const userRef = firestore.doc(`users/${userAuth.uid}`) const snapshot = await userRef.get() if(!snapshot.exists) { const {displayName, email} = userAuth; const createdAt = new Date(); try { await userRef.set({ displayName, email, ...additionalData }) } catch (error){ console.log('error creating user' error.message) } } return userRef }間違っていたら教えてください
- 投稿日:2021-01-10T03:44:20+09:00
Next.js公式examples集を分類(2021年1月版)
はじめに
Next.jsの公式サンプルは前回(2020年7月)から34本増えて合計268本あります。新たに追加されたサンプルには(new)がついています。(2021/01/10)
しかし、このままではどれを見たらいいのかわからないので主観で分類してみました。(基礎)Next.jsで基礎的な内容を扱っているサンプル。
(公式)公式ドキュメント で説明するのに使われているサンプル等。※今回の更新で一番目についたのはwith-mysqlで、その他DB関連も多く追加されていました。
Next.js公式examples集
Next.jsの基礎1易しい basic-css (基礎)(公式)CSS in JSを使っている basic-export (基礎)最も基本的な使用法 dynamic-routing (基礎)(公式)動的ルーティングの使用例 environment-variables (基礎)環境変数の使い方 head-elements (基礎)ヘッド要素の使用例 hello-world (基礎)Next.jsの基本中の基本 layout-component (基礎)一般的な使用例 nested-components (基礎)コンポーネントをネストして利用する使用例 using-router (基礎)(公式)コンポーネントの代わりにnext/routerを使ってページをリンクする with-app-layout (基礎)_app.jsを使用してすべてのページにグローバルレイアウトを実装する with-loading (基礎)ページ切替時に時間がかかる時、Loading画面を表示する技術
Next.jsの基礎2普通 active-class-name Next独自のLinkを使ってclassNameでプロパティを設定する使用例 catch-all-routes (公式)ページをデータから自動的に作成してくれる機能 data-fetch (公式)サーバーとクライアントでデータをフェッチするのが非常に簡単になります。 gh-pages Nextの最も基本的なアイデアの使用方法 progressive-render プログレッシブサーバーサイドレンダリングを実装するアプリの使用例 ssr-caching 一度SSRしたページをキャッシュして使用する使用例 with-absolute-imports 絶対インポートを使用したアプリの使用例 with-context-api アプリでreact context apiを使用する方法 with-dynamic-app-layout app.jsを使用してページの_dynamicレイアウトを実装する方法 with-dynamic-import (公式)モジュールを動的にインポートする方法 with-env-from-next-config-js (公式)next.config.jsを使って環境変数をビルド時に設定します。 with-http2 HTTP2サーバーを使った最も基本的な使用例 with-next-page-transitions ページ間移動時において読み込み状態を簡単に追加 with-prefetching ページをプリフェッチ(事前読み込み)するサンプルアプリ with-react-helmet next.jsとreact-helmetを組み合わせる方法の最小限の使用例 ドキュメントヘッドへのすべての変更を管理します。 with-shallow-routing (公式)ShallowRoutingExample with-static-export (公式)APIからデータをフェッチするNext.jsアプリケーションを静的HTMLファイルにエクスポートして、ページの動的リストを生成する方法 with-typescript-eslint-jest NextJS Typescriptボイラープレート with-typescript-types TypeScript型システムをNext.jsに統合する方法 with-typescript タイプスクリプトを使って型を適用 with-zones (公式)マルチゾーン機能を使用して、複数のアプリを1つのアプリとして使用できます。
Next.jsの基礎3 2021年1月版追加分 (new)fast-refresh-demo Next.jsにはFast Refreshが搭載されており、Reactコンポーネントに加えられた編集を即座にフィードバックすることができます。このデモでは、編集後やエラーが発生した場合に、自動インクリメント値とクラシックカウンタの状態がどのように保存されるかを見ます。 (new)redirects Next.jsでリダイレクトを使用して、入ってきたリクエストパスを別の宛先パスにリダイレクトする方法 (new)rewrites Next.jsで書き換えを使用して、着信要求パスを別の宛先パスにマップする方法
pwa関連 (new)progressive-web-app next-pwaを使用して、Workboxを利用したプログレッシブウェブアプリ(PWA)を作成します。
UI関連ant with-ant-design-less Ant Design of ReactとともにNext.jsを使用する方法 with-ant-design-mobile antd-mobileとともにNext.jsを使用する方法 with-ant-design-pro-layout-less Ant Design Pro Layout of React.とともにNext.jsを使用する方法 with-ant-design Ant Design of ReactとともにNext.jsを使用する方法
UI関連その他 (new)with-chakra-ui-typescript このサンプルでは、typescriptを使用してNext.jsアプリ内のコンポーネントライブラリとしてchakra-uiを使用する方法を紹介します。 (new)with-ionic-typescript 高品質のクロスプラットフォームネイティブおよびWebアプリエクスペリエンスを構築するためのオープンソースモバイルUIツールキット。 (new)with-mdbreact レスポンシブでモバイルファーストのウェブサイトやアプリを構築するためのUIキット with-atlaskit Atlaskit of ReactとともにNext.jsを使用する方法AltassianのオフィシャルUIライブラリ with-chakra-ui Webサイトやアプリの作成を非常に簡単にする、アクセス可能で再利用可能で構成可能なReactコンポーネントのセットchakra-uiをNext.jsアプリ内のコンポーネントライブラリとして使用する方法 with-grommet Grommet UI library with-material-ui (人気)(Material-UI公式サイトのサンプル) mui-org/material-ui/examples/nextjs/ with-patternfly RedHatが作っているUIフレームワークUIパターン集 with-rebass UIコンポーネントRebassはReactのブートストラップです。
Firebase関連 (new)with-supabase-auth-realtime-db Supabaseは、Firebaseのオープンソースの代替手段です。 with-firebase-authentication サーバーレスAPIを使用したFirebase認証の使用例 with-firebase-cloud-messaging FirebaseCloudMessagingの使用例 with-firebase-hosting Firebaseホスティングの使用例 with-firebase クライアントサイドアプリケーション用のFirebaseの簡単な設定です。
API Routes編 api-routes-cors (公式)Cross-OriginResourceSharing(CORS)追加のHTTPヘッダーを使用して、ある起点で実行されているWebアプリケーションに、異なる起点から選択されたリソースへのアクセスを許可するようにブラウザーに指示するメカニズムです。 api-routes-middleware (公式)APIルート api-routes-rest (公式)独自のルートを構築する簡単なソリューションを提供するAPIルートが付属しています。このサンプルは、それを使用してREST APIを作成する方法 api-routes (公式)基本的なAPIルートの使用例
API Routes編 GraphQL関連 api-routes-graphql (公式)GraphQL Server apollo-server-micro with-graphql-faunadb FaunaDBGraphqlスターターの使用例-FaunaDBゲストブック with-graphql-hooks GraphQLフックの使用例。GraphQL Hooksは、最小限のフック優先のGraphQLクライアントになることを目的としたNearFormのライブラリです。 with-graphql-react graphql-react最新のコンテキストを使用したReactのGraphQLクライアント with-react-relay-network-modern The production-ready GraphQL client for React. with-reason-relay GraphQL backend with-relay-modern Facebookが開発 Next.jsの9.3で導入されたgetStaticProps, および9.4で導入されたIncremental Static Regenerationは、Relayと非常に相性がいい The production-ready GraphQL client for React. with-typescript-graphql GraphQLとtypescriptの使用例 with-urql 高度にカスタマイズ可能で用途の広いGraphQLクライアント
API Routes編 apollo関連 (new)api-routes-rate-limit このサンプルではlru-cacheを使用してAPIルート(サーバーレス関数)の単純なレートリミッターを実装します。lru cacheは最も使用頻度の低いアイテムを削除するキャッシュオブジェクトです。 (new)with-apollo-neo4j-graphql GraphQLとApolloでNeo4jデータベースを使用するNextの簡単なセットアップです。 Neo4jのMoviesデータセットの使用例です。 api-routes-apollo-server-and-client-auth ApolloはGraphQLクライアント api-routes-apollo-server-and-client ApolloはGraphQLクライアント api-routes-apollo-server ApolloはGraphQLクライアント with-apollo-and-redux ApolloはGraphQLクライアント with-apollo ApolloはGraphQLクライアント
DB関連 prisma編 with-prisma Node.jsおよびTypeScript用の次世代ORM
DB関連 mysql編 (new)with-mysql Next.jsプロジェクトでMySQLを使用する使用例
DB関連 その他 (new)with-deta-base Deta Baseは、エンドユーザーのシンプルさに重点を置いた、フルマネージドで高速、スケーラブルで安全なNoSQLデータベースです。 (new)with-knex Knexは、Postgres や MySQL を含むさまざまな SQL データベースで動作する SQL クエリビルダーです。このサンプルでは、Next.js と Knex を使って Postgresデータベースに接続してクエリを実行する方法です。 (new)with-mongodb このサンプルはMongoDBに接続してNext.jsアプリのバックエンドとして使用する方法 (new)with-neo4j Neo4jは、データだけでなく、データの関係性を活用するために一から構築されたネイティブのグラフデータベースです。 (new)with-redis Redisは、Key-Value型 の NoSQLデータベースです。 with-mongodb-mongoose MongoDB with-realm-web MongoDBRealmWebSDK
コンポーネント関連 with-carbon-components IBM's carbon-components-react
server関連 custom-server-actionhero Action Hero custom-server-express (公式)Express Webアプリケーション custom-server-fastify Fastify custom-server-hapi (公式)Secure Framework custom-server-koa (公式)new web framework designed custom-server-polka Express.jsの代替品 custom-server-typescript Nodemonを使用してサーバーとクライアントの両方でTypeScriptを使用し、Next.jsユニバーサルコードに影響を与えずにサーバーコードをライブでリロードする方法 custom-server カスタムサーバーの使用例
storybook関連 (new)with-storybook-styled-jsx-scss このサンプルはStorybookでレンダリングされTypeScriptで記述されたコンポーネントStyled-jsx(SCSSを使用)の使用例です。 with-storybook UIコンポーネントを開発するためのオープンソースツール
検索関連 with-algolia-react-instantsearch 検索の実装と検索の分析
監視関連 with-sentry アプリケーション監視プラットフォーム
リッチテキスト関連 with-draft-js RichTextEditorFrameworkforReact with-quill-js powerfulrichtexteditor with-slate リッチテキストThisiseditablerichtext
認証関連 auth0 (認証)(有料有り)認証サポートを簡単に追加する方法 with-cookie-auth-fauna (認証)(有料有り)ユーザーを認証し、トークンを安全な(JS以外の)Cookieに格納します。 with-iron-session (認証)署名および暗号化されたCookieを使用してセッションデータを格納する認証システムを作成 with-magic (認証)(有料有り)Magic電子メールベースのマジックリンクを使用した、Cookieベースのパスワードなし認証を特徴としています。 with-next-auth (認証)オープンソースで使いやすく、デフォルトで安全な認証ライブラリを備えたnext-authを使用 with-passport-and-next-connect (認証)Passport.jsでnext-connectおよびcookieベースの認証を使用して、基本的なCRUDアプリを作成します。 with-passport (認証)ユーザー名とパスワードを使用したCookieベースの認証 with-userbase (認証)(有料有り)Userbaseユーザーアカウントとデータの永続性を静的サイトに追加する最も簡単な方法です
CSS関連 tailwindcss編 with-tailwindcss-emotion tailwindCSS with-tailwindcss (公式)tailwindCSS
CSS関連 styled-jsx編 (new)with-styled-jsx Next.jsにはstyled-jsxが付属しており、CSSを完全にサポートするスコープ付きスタイルのコンポーネントを作成できます。 with-styled-jsx-plugins CSS styled-jsxプラグインを使用 with-styled-jsx-scss PostCSS、SASS(SCSS)、LESS、またはstyled-jsxを備えたその他のプリプロセッサを使用できます。
CSS関連 その他 (new)with-cssed CSS-in-JSlibraryであるcssedの使用例 (new)with-react-md-typescript このサンプルではreactのマテリアルデザイン、Next.js、およびTypescriptアプリをセットアップします。 (new)with-reactstrap reactstrapをNext.jsで使用する方法。reactstrapはBootstrap4のステートレスreactコンポーネント。 with-aphrodite (公式)CSS in JS aphroditeを使用したアプリの使用例 with-astroturf CSS in JS stroturfを使用したアプリの使用例 with-cxs (公式)CSS in JS minimal CSS in JS cxsを使用したアプリの使用例 with-emotion CSS in JS SSR中にサーバーデータを直接Next.jsページに渡す with-fela (公式)CSS in JS with-filbert CSS in JSソリューション(フレームワーク)filbert-jsでNext.jsを使用する with-glamor (公式)CSS in JS CSS関連スタイリングソリューションの使用方法 with-goober 小さなcss-in-js with-linaria CSS linariaを使用したアプリの使用例 with-next-css CSSモジュールサポートの使用方法 with-next-less CSS Next.js + Less with-next-sass Sass/Scssモジュールサポートの使用方法 with-rbx-bulma-pro Bulma is simply a collection of CSSclasses. with-react-bootstrap react-bootstrap react用に再構築されたbootstrap with-react-jss JSSはCSSのオーサリングツール with-react-md (紹介ページが消えている、V2になってページが移動した?)SCSSreact-md (React Material Design) with-react-with-styles CSS in JS with-semantic-ui CSSフレームワーク Semantic UI Reactと一緒にNext.jsを利用する方法 with-stitches CSS in JS with-style-sheet CSS in JSlibrarystyle-sheet with-styled-components-rtl 右から左にすると、サイト内のすべての要素を「反転」して、右から左に読む文化(たとえば、アラビア語)のニーズに合わせることができます。 with-styled-components (公式)CSS in JS CSSstyled-components with-styletron (公式)CSS in JSスタイルソリューション with-typescript-styled-components StyledComponentsとTypeScriptの使用例。CSS in JSの中で最も人気のあるライブラリ with-typestyle CSSスタイルソリューションを使用する方法
状態管理redux関連 with-redux-code-splitting Redux関連 with-redux-observable Redux関連 with-redux-persist Redux関連 with-redux-saga Redux関連 with-redux-thunk Redux関連 with-redux-toolkit Redux関連 with-redux-wrapper Redux関連 with-redux Redux関連 with-rematch このサンプルには2つのページがあります。最初のページには、同期的または非同期的にインクリメントできるカウンタがあります。2番目のページはgithubユーザーのリストを表示するページです。このエンドポイントを使ってgithub APIからデータを取得します。 rematchはreduxを使ったユーティリティなので、store.jsやwithRematchのような要素はwith-reduxの使用例と非常に似ています。redux が nextjs とどのように統合されているかをよく知らない方は、ここで with-reduxの使用例を見てから読んでください。RematchはReduxの拡張機能に過ぎないので、多くの要素は同じです。
状態管理その他 (new)with-zustand React向け軽量ステート管理ライブラリの使用例 with-kea 状態管理フレームワーク with-mobx-react-lite 状態管理 with-mobx-state-tree-typescript 状態管理 with-mobx-state-tree 状態管理 with-mobx 状態管理アプリのグローバルな状態を取得したい場合 with-overmind 状態管理 with-recoil 状態管理ライブラリ with-unstated unstated-nextReact状態管理ライブラリ
amp関連 amp-first AMPファーストサイトのボイラープレートを設定 amp-story Next.jsとAMP機能を使用してamp-storyを含むAMPページを作成する方法 amp (公式)Next.jsとAMP機能を使用してAMPページを作成する方法
国際化 (new)i18n-routing Next.js ver10.0から国際化が組み込まれました。https://nextjs.org/docs/advanced-features/i18n-routing with-i18n-rosetta 汎用国際化ライブラリ with-lingui LinguiJS-JavaScriptでのシームレスな国際化 with-next-i18next i18nextに基づく国際化をnext.jsアプリケーションに追加する最も簡単な方法 with-next-translate next-translate Next.jsページを翻訳するためのツールです。 with-react-intl FormatJSクライアントとサーバーでWebアプリを国際化します。
AWS関連 with-aws-amplify-typescript AWSAmplifyは、モバイルおよびフロントエンドのウェブデベロッパーがAWSを利用して安全でスケーラブルなフルスタックアプリケーションを構築できるようにするツールとサービスのセットです。 with-aws-amplify AWSAmplifyは、モバイルおよびフロントエンドのウェブデベロッパーがAWSを利用して安全でスケーラブルなフルスタックアプリケーションを構築できるようにするツールとサービスのセットです。
テスト関連 with-jest テスト with-mocha テスト with-tesfy A/Bテストと機能フラグ
システム関連 webpack bundle babel analyze-bundles @next/bundle-analyzerの使い方 with-babel-macros babel-plugin-macrosは、ユーザーがビルドシステムにbabelプラグインを追加することなくコンパイル時のコード変換を使用するライブラリの標準インターフェイスを定義します with-custom-babel-config カスタムBabel構成の使用例 with-webpack-bundle-size-analyzer Webpackバンドルのサイズに寄与しているものを見つけるのに役立つ小さなユーティリティ。
cms関連 (new)cms-kontent Next.jsとKontentを使用して静的に生成されたブログの使用例 blog-starter-typescript Next.js、Markdown、TypeScriptを使用して静的に生成されたブログの使用例 blog-starter (公式)Next.jsとMarkdownを使用して静的に生成されたブログの使用例 cms-agilitycms AgilityCMS cms-buttercms ButterCMS cms-contentful (公式)Contentful cms-cosmic Cosmic cms-datocms (公式)DatoCMS cms-graphcms GraphCMS cms-prismic (公式)Prismic cms-sanity (公式)Sanity cms-storyblok Storyblok cms-strapi (公式)Strapi cms-takeshape (公式)TakeShape cms-wordpress (公式)WordPress with-netlify-cms Gitワークフロー用のオープンソースのコンテンツ管理システム
デスクトップアプリケーション関連 with-electron-typescript デスクトップアプリケーションElectron application example with typescript with-electron デスクトップアプリケーションElectron application example
mdx関連 (new)with-mdx-remote next-mdx-remoteライブラリを使用して簡単なブログを構築する方法 with-mdx next.jsアプリのトップレベルページとしてMDXを使用する方法
google関連 (new)with-google-tag-manager Googleタグマネージャーを使用したアプリの使用例 with-google-analytics-amp AMPと組み合わせてGoogleアナリティクスとともにNext.jsを使用する方法 with-google-analytics GoogleアナリティクスとともにNext.jsを使用する方法 with-react-ga react-ga React Google Analytics Module
preact関連 using-preact 高速で小型のReactと言われるpreactを使用する使用例
サイトマップ関連 (new)with-next-sitemap next-sitemapを使用してすべてのページ(すべての事前レンダリング/静的ページを含む)のサイトマップファイルを生成する使用例 (new)with-sitemap Next.jsアプリのページに基づいてファイルを生成する方法
既存プロジェクトからの移行関連 custom-routes-proxying このサンプルでは、Next.jsの新しいカスタムルート機能を使って、リクエストをアップストリームサーバーにプロキシする最も基本的な使用例。pages/index.js、pages/about.js、pages/hello/[slug].jsの3つのページがあります。これらのページはすべてNext.jsと照合され、それ以外のパスはアップストリームサーバーにプロキシされます。このアプローチは、アプリケーションをインクリメンタルにNext.jsに移行しようとしているが、既存のアプリケーションにフォールバックする必要がある場合に非常に便利です。Next.jsアプリケーションにページを1つずつ追加し、移行していないページについては、移行できるようになるまでNext.jsが既存のアプリケーションにプロキシすることができます。
docker関連 with-docker 実行時にDockerアプリケーションのカスタム環境変数を設定する方法
画像関連 (new)image-component Next.js の Image Componentを使用して、最適化されたレスポンシブ画像を提供する方法 (new)with-unsplash 自由に使用できる画像のインターネットソース。 svg-components .babelrcを使用して、.svgファイルをインポートし、それらをReactコンポーネントとしてレンダリングするためのサポートを追加します。 with-three-js threejsはWebGL レンダラを持つ軽量な 3D ライブラリ。このライブラリには Canvas 2D、SVG、CSS3Dのレンダラーも用意されています。
動画関連 with-hls-js HTTPライブストリーミングクライアントを実装するJavaScriptライブラリです。 with-mux-video この使用例では、APIファーストのビデオプラットフォームであるMuxVideoを使用しています。この使用例では、Next.jsアプリケーションでのビデオのアップロードと再生を取り上げています。 with-videojs デフォルトのスタイルの処理を含む、Video.jsとともにNext.jsを使用する方法
アニメーション関連 (new)with-gsap gsapはアニメーションライブラリです。 with-framer-motion motionはオープンソースで本番環境に対応したモーションWeb上のReact用のライブラリ
moved、removed、非推奨、廃止 page-transitions (インストール不要)このサンプルは非推奨になり、削除されました。 parameterized-routing (インストール不要)このサンプルは非推奨になり、削除されました。 with-cookie-auth (非推奨)(認証)このサンプルは非推奨になり、次のいずれかを参考にしてください。auth0 with-cookie-auth-fauna with-passport with-iron-session with-next-auth with-dotenv (インストール不要)Next.js9.4からサポートされています。 with-firebase-authentication-serverless (moved)with-firebase-authentication with-glamorous (インストール不要)glamorousは非推奨になり、エモーションが採用されました。 with-global-stylesheet-simple (インストール不要)このサンプルは非推奨になりました。代わりにexamples/with-next-cssを使用してください。 with-global-stylesheet (インストール不要)このサンプルは非推奨になりました。代わりにexamples/with-next-cssを使用してください。 with-markdown (インストール不要)Markdownの使い方はcanary/examples/blog-starterを見てください。 with-next-routes (インストール不要)動的ルートがデフォルトでサポートされるようになりました with-now-env (インストール不要) Next.jsは9.4以降、環境変数の読み込みを自動的にサポートします。 with-pretty-url-routing (インストール不要)動的ルートはデフォルトでサポートされるようになりました with-sentry-simple (インストール不要)(moved)with-sentryの方を使用してください。アプリケーション監視プラットフォーム with-strict-csp-hash (インストール不要) (moved)このサンプルはwith-strict-cspに移動しました with-styled-jsx-postcss (moved) このサンプルは/examples/with-styled-jsx-pluginsに移動しました with-sw-precache (インストール不要)canary/examples/with-next-offlineの使用をおすすめします。 with-universal-configuration-build-time (インストール不要)Next.js9.4以降、環境変数の読み込みを自動的にサポートします。 with-universal-configuration-runtime (インストール不要)Next.js9.4以降、環境変数の読み込みを自動的にサポートします。 with-webpack-bundle-analyzer (moved)このサンプルはanalyze-bundlesに移動しました。
古い、数年更新がない with-reflux 古い SSR中にサーバーデータをNext.jsページに直接渡す
その他 (new)with-facebook-pixel Facebook Pixelの使用例 (new)with-mqtt-js Next.jsでMQTT.jsを使用する方法 MQTT.jsは、node.jsおよびブラウザー用のJavaScriptで記述されたMQTTプロトコルのクライアントライブラリです。 (new)with-msw Mock Service Workerは、ブラウザとノード用のAPIモックライブラリです。 (new)with-paste-typescript Pasteは、Twilioでアクセス可能で、まとまりのある、高品質のカスタマーエクスペリエンスを構築するために使用される設計システムです。Pasteは、Sketch and Reactで顧客のUIを構築するのに役立つツールとアセットで製品デザイナーとエンジニアをサポートします。 (new)with-portals-ssr ポータルは、親コンポーネントのDOM階層の外側に存在するDOMノードに子をレンダリングするためのファーストクラスの方法を提供します。 (new)with-portals ポータルは、親コンポーネントのDOM階層の外側に存在するDOMノードに子をレンダリングするためのファーストクラスの方法を提供します。 (new)with-service-worker ServiceWorkerをNext.jsアプリケーションに追加する方法 with-cerebral 一般的なJavaScriptフレームワーク用の宣言型の状態および副作用管理ソリューション with-custom-reverse-proxy リバースプロキシの使用例 with-expo-typescript Next.js、Expo、およびTypeScriptを使用してユニバーサルReactアプリを作成するためのスタータープロジェクトです。 with-expo Next.jsとExpoを使用してユニバーサルReactアプリを作成するためのスタータープロジェクトです。 with-flow Flow静的型チェッカーFlowを使用したアプリの使用例 flowはJavaScriptの静的タイプチェッカーです。 with-monaco-editor モナコエディタは VS Codeを動かすコードエディタです。 with-next-offline next-offlineプラグインの使用方法 with-next-seo Next.jsでSEOを管理するのに役立つプラグインであるnext-seoを統合する方法 with-orbit-components Orbitは、Kiwi.comの特定のニーズに合わせて作成されたオープンソースのデザインシステムで、旅行プロジェクトのニーズにも対応しています。 with-polyfills ポリフィルを使用したアプリの使用例 警告:このサンプルは、ポリフィルを追加するための推奨される方法ではなく、バンドルで問題を引き起こすことが知られています。 with-react-multi-carousel react-multi-carouselは、外部依存関係のない複数のアイテムをサポートするサーバー側でレンダリングするカルーセルを提供するReactコンポーネントです。 with-react-native-web react-native-webを使用して、プラットフォームに依存しないReactNativeのコンポーネントとAPIをWebに取り込む方法 with-react-toolbox React Toolbox 2.0以降を使用してください。 with-reasonml-todo ReasonMLおよびReasonReactコンポーネントを使用したサンプルアプリ with-reasonml ReasonMLおよびReasonReactコンポーネントを使用したサンプルアプリ with-route-as-modal 多くの人気のソーシャルメディアでは、投稿を開くとURLが更新されますが、ナビゲーションはトリガーされず、代わりにモーダル内にコンテンツが表示されます。この動作により、ユーザーは現在のUIコンテキスト(スクロール位置)を失うことはありません。URLは引き続き投稿の実際のページの場所を反映しており、更新するとユーザーはそこに移動します。この動作により、SEOを無視することなく優れたUXが保証されます。 このサンプルは、ルートに基づいてモーダルを条件付きで表示する方法。 with-segment-analytics 分析機能を備えたアプリの使用例 with-stencil ステンシルは、Webコンポーネント(より具体的にはカスタム要素)を生成するコンパイラです。ステンシルは、最も人気のあるフレームワークの最高の概念をシンプルなビルドタイムツールに組み合わせています。 with-stomp Next.jsアプリケーション内でSTOMPを使用する方法。STOMPは、単純なテキスト指向のメッセージングプロトコルです。 with-strict-csp スクリプトハッシュを生成する厳密なCSPを使用したアプリの使用例 with-stripe-typescript TypeScriptとreact-stripe-jsでStripeを使用した使用例。 Stripe はインターネットビジネスのための決済プラットフォームです。 with-web-worker worker-pluginを利用してWebWorkersでコードを実行する方法 with-webassembly WebAssemblyの使用例 with-why-did-you-render why-did-you-renderの簡単な使用方法。 with-xstate XStateをNext.jsに統合する方法。 JavaScriptとTypeScriptの有限状態マシンと最新のWeb用のステートチャート。 with-yarn-workspaces ワークスペースはパッケージアーキテクチャを設定する新しい方法で、Yarn 1.0 からデフォルトで利用可能です。これにより、複数のパッケージを設定することができ、yarn install を一度だけ実行して、すべてのパッケージを一度にインストールすることができます。 with-zeit-fetch Next.jsアプリケーションで@zeit/fetchを使用する方法
前回の調査から削除されたもの with-emotion-11 CSS in JS with-stitches-styled CSS in JS with-storybook-typescript (インストール不要)削除されました。 z-experimental-refresh (実験的) アプリケーションやプロジェクトでは、これらの機能を(まだ)使用しないでください。 Yarn workspace機能で2個目以降のインストール時間を短縮
前提
複数のサンプルを試したい場合に、一つ一つインストールしていくと非常に時間がかかってしまいます。どうにか時間を短縮したいという場合。
- 問題点 サンプルによっては正常に動かないものがあります。 認証系など外部に頼るものをインストールした時。 他には、数百個同時にインストールをした時。 どちらも解決方法は不明です。
もしエラーが出た場合
そのexampleのREAD.MEを読んでみましょう。
npm install
oryarn
という単純なインストール方法でない可能性が高いです。
- 使用する機能
Yarn workspace
ワークスペース | Yarn ← 詳細はこちらを御覧ください。Yarn workspace機能を利用してリポジトリを一元管理します。
準備&初期設定
まずはNext.jsリポジトリの中にある
examples/
を取得します。公式Next.jsリポジトリから
git clone https://github.com/vercel/next.js.git
Next.jsの公式リポジトリからNext.js本体をgit clone
します。
もしくはgithubのDownload ZIP機能でローカルフォルダに保存します。git cloneした、もしくはダウンロードしたzipファイルを解凍したフォルダの中に
examples/
フォルダがありますので取り出します。[nextjs-examples]というexamplesを管理するフォルダを作ってこの中に保存します。
( []内の名前は自由に変更可能です。)現在のフォルダ構造
[nextjs-examples]/
└ examples/
├ [exampleA]/
├ [exampleB]/
└ [exampleC]/[nextjs-examples]/はルートフォルダになります。
[nextjs-examples]/をVSCodeで開きます。
ターミナルから
yarn init --yes --private
を実行します。package.jsonが出来ます。
package.json{ "name": "nextjs-examples", "version": "1.0.0", "main": "index.js", "license": "MIT", "private": true }※privateはtrueにする必要があります。
現在のフォルダ構造
[nextjs-examples]/
├ examples/
│ ├ [exampleA]/
│ ├ [exampleB]/
│ └ [exampleC]/
├ node_modules/
└ package.json
└ yarn.lock最初の一つをインストールする
まずは、examplesの中でNext.jsを初めて触るのに手頃な「basic-export」をインストールしてみます。
package.jsonを開きます。
"workspaces"を追記して、その中に
インストールする"examples/basic-export"を書きます。package.json{ "name": "nextjs-examples", "version": "0.1.0", "main": "index.js", "license": "MIT", "private": true, "workspaces": [ "examples/basic-export" ] }インストールするexampleを決めたらルートで
yarn
もしくはyarn install
を実行します。
最初なので数分かかると思います。インストール完了後に、
cd examples/basic-export
yarn dev
これでbasic-exportがサーバーで起動し、
http://localhost:3000/
で実行されているのが確認できます。サーバーの起動を停止して(Ctrl+C)
次のサンプルをインストールしてみます。
cd ../..
(ルート[nextjs-examples]/)
に戻ります。examplesの「basic-css」と「dynamic-routing」の2つを追加してみます。
package.json{ "name": "nextjs-examples", "version": "0.2.0", "main": "index.js", "license": "MIT", "private": true, "workspaces": [ "examples/basic-export", "examples/basic-css", "examples/dynamic-routing" ] }ルートフォルダに戻り
(ルート[nextjs-examples]/)
yarn
oryarn install
を実行してみます。。Done in 6.78s.でインストールが完了しました、早いですね。
それぞれのサブフォルダに移動して
yarn dev
を実行してみます。
3つとも動くのが確認できました。では次に、「Next.jsの基礎1易しい」を全部インストールしてみましょう。
package.json{ "name": "nextjs-examples", "version": "0.3.0", "main": "index.js", "license": "MIT", "private": true, "workspaces": [ "examples/basic-export", "examples/basic-css", "examples/dynamic-routing", "examples/environment-variables", "examples/head-elements", "examples/hello-world", "examples/layout-component", "examples/nested-components", "examples/using-router", "examples/with-app-layout", "examples/with-loading" ] }ルートフォルダに戻り ([nextjs-examples]/)
yarn
oryarn install
を実行してみます。
Done in 3.71s.でインストールが完了しました。
インストールするものがほぼありませんので一瞬で終わりましたね。全部の動作確認はしていませんが、
エラーなども特に出ていないので、
一気にNext.jsの基礎2普通を全部インストールしてみましょう。package.json{ "name": "nextjs-examples", "version": "0.4.0", "main": "index.js", "license": "MIT", "private": true, "workspaces": [ "examples/basic-export", "examples/basic-css", "examples/dynamic-routing", "examples/environment-variables", "examples/head-elements", "examples/hello-world", "examples/layout-component", "examples/nested-components", "examples/using-router", "examples/with-app-layout", "examples/with-loading", "examples/active-class-name", "examples/catch-all-routes", "examples/data-fetch", "examples/gh-pages", "examples/progressive-render", "examples/ssr-caching", "examples/with-absolute-imports", "examples/with-context-api", "examples/with-dynamic-app-layout", "examples/with-dynamic-import", "examples/with-env-from-next-config-js", "examples/with-http2", "examples/with-next-page-transitions", "examples/with-prefetching", "examples/with-react-helmet", "examples/with-shallow-routing", "examples/with-static-export", "examples/with-typescript-eslint-jest", "examples/with-typescript-types", "examples/with-typescript", "examples/with-zones" ] }Done in 165.56s.でインストールが完了しました
「typescript」等が追加されているので少し時間がかかりました。14個ものexampleを追加インストールしたのに、こんな短時間でインストールが完了しました。
このようにyarn workspaces機能を使うことで最初の一個以外残りはほぼ時間をかけることなくインストールが出来ました。追記用全リスト
Next.jsの基礎2普通
"examples/active-class-name",
"examples/catch-all-routes",
"examples/data-fetch",
"examples/gh-pages",
"examples/progressive-render",
"examples/ssr-caching",
"examples/with-absolute-imports",
"examples/with-context-api",
"examples/with-dynamic-app-layout",
"examples/with-dynamic-import",
"examples/with-env-from-next-config-js",
"examples/with-http2
"examples/with-next-page-transitions",
"examples/with-prefetching",
"examples/with-react-helmet",
"examples/with-shallow-routing",
"examples/with-static-export",
"examples/with-typescript-eslint-jest",
"examples/with-typescript-types",
"examples/with-typescript",
"examples/with-zones"Next.jsの基礎3 2021年1月版追加分
"examples/fast-refresh-demo",
"examples/redirects",
"examples/rewrites"pwa関連
"examples/progressive-web-app"UI関連ant",
"examples/with-ant-design-less",
"examples/with-ant-design-mobile",
"examples/with-ant-design-pro-layout-less",
"examples/with-ant-design"UI関連その他
"examples/with-chakra-ui-typescript",
"examples/with-ionic-typescript",
"examples/with-mdbreact",
"examples/with-atlaskit",
"examples/with-chakra-ui",
"examples/with-grommet",
"examples/with-material-ui",
"examples/with-patternfly",
"examples/with-rebass"Firebase関連
"examples/with-supabase-auth-realtime-db",
"examples/with-firebase-authentication",
"examples/with-firebase-cloud-messaging",
"examples/with-firebase-hosting",
"examples/with-firebase"API Routes編
"examples/api-routes-cors",
"examples/api-routes-middleware",
"examples/api-routes-rest",
"examples/api-routes"API Routes編 GraphQL関連
"examples/api-routes-graphql",
"examples/with-graphql-faunadb",
"examples/with-graphql-hooks",
"examples/with-graphql-react",
"examples/with-react-relay-network-modern",
"examples/with-reason-relay",
"examples/with-relay-modern",
"examples/with-typescript-graphql",
"examples/with-urql"API Routes編 apollo関連
"examples/api-routes-rate-limit",
"examples/with-apollo-neo4j-graphql",
"examples/api-routes-apollo-server-and-client-auth",
"examples/api-routes-apollo-server-and-client",
"examples/api-routes-apollo-server",
"examples/with-apollo-and-redux",
"examples/with-apollo"DB関連 prisma編
"examples/with-prisma"DB関連 mysql編
"examples/with-mysql"DB関連 その他
"examples/with-deta-base",
"examples/with-knex",
"examples/with-mongodb",
"examples/with-neo4j",
"examples/with-redis",
"examples/with-mongodb-mongoose",
"examples/with-realm-web"コンポーネント関連
"examples/with-carbon-components",
server関連
"examples/custom-server-actionhero",
"examples/custom-server-express",
"examples/custom-server-fastify",
"examples/custom-server-hapi",
"examples/custom-server-koa",
"examples/custom-server-polka",
"examples/custom-server-typescript",
"examples/custom-server",
storybook関連
"examples/with-storybook-styled-jsx-scss",
"examples/with-storybook"検索関連
"examples/with-algolia-react-instantsearch"監視関連
"examples/with-sentry"リッチテキスト関連
"examples/with-draft-js",
"examples/with-quill-js",
"examples/with-slate"認証関連
"examples/auth0
"examples/with-cookie-auth-fauna",
"examples/with-iron-session",
"examples/with-magic",
"examples/with-next-auth",
"examples/with-passport-and-next-connect",
"examples/with-passport",
"examples/with-userbase"CSS関連 tailwindcss編
"examples/with-tailwindcss-emotion",
"examples/with-tailwindcss"CSS関連 styled-jsx編
"examples/with-styled-jsx",
"examples/with-styled-jsx-plugins",
"examples/with-styled-jsx-scss"CSS関連 その他
"examples/with-cssed",
"examples/with-react-md-typescript",
"examples/with-reactstrap",
"examples/with-aphrodite",
"examples/with-astroturf",
"examples/with-cxs",
"examples/with-emotion",
"examples/with-fela",
"examples/with-filbert",
"examples/with-glamor",
"examples/with-goober",
"examples/with-linaria",
"examples/with-next-css",
"examples/with-next-less",
"examples/with-next-sass",
"examples/with-rbx-bulma-pro",
"examples/with-react-bootstrap",
"examples/with-react-jss",
"examples/with-react-md",
"examples/with-react-with-styles",
"examples/with-semantic-ui",
"examples/with-stitches",
"examples/with-style-sheet",
"examples/with-styled-components-rtl",
"examples/with-styled-components",
"examples/with-styletron",
"examples/with-typescript-styled-components",
"examples/with-typestyle"状態管理redux関連
"examples/with-redux-code-splitting",
"examples/with-redux-observable",
"examples/with-redux-persist",
"examples/with-redux-saga",
"examples/with-redux-thunk",
"examples/with-redux-toolkit",
"examples/with-redux-wrapper",
"examples/with-redux",
"examples/with-rematch"状態管理その他
"examples/with-zustand",
"examples/with-kea",
"examples/with-mobx-react-lite",
"examples/with-mobx-state-tree-typescript",
"examples/with-mobx-state-tree",
"examples/with-mobx",
"examples/with-overmind",
"examples/with-recoil",
"examples/with-unstated",
"examples/amp関連
"examples/amp-first",
"examples/amp-story",
"examples/amp"国際化
"examples/i18n-routing",
"examples/with-i18n-rosetta",
"examples/with-lingui",
"examples/with-next-i18next",
"examples/with-next-translate",
"examples/with-react-intl"AWS関連
"examples/with-aws-amplify-typescript",
"examples/with-aws-amplify"テスト関連
"examples/with-jest",
"examples/with-mocha",
"examples/with-tesfy"システム関連 webpack bundle babel",
"examples/analyze-bundles",
"examples/with-babel-macros",
"examples/with-custom-babel-config",
"examples/with-webpack-bundle-size-analyzer"cms関連
"examples/cms-kontent",
"examples/blog-starter-typescript",
"examples/blog-starter",
"examples/cms-agilitycms",
"examples/cms-buttercms",
"examples/cms-contentful",
"examples/cms-cosmic",
"examples/cms-datocms",
"examples/cms-graphcms",
"examples/cms-prismic",
"examples/cms-sanity",
"examples/cms-storyblok",
"examples/cms-strapi",
"examples/cms-takeshape",
"examples/cms-wordpress",
"examples/with-netlify-cms"デスクトップアプリケーション関連
"examples/with-electron-typescript",
"examples/with-electron"mdx関連
"examples/with-mdx-remote",
"examples/with-mdx"google関連
"examples/with-google-tag-manager",
"examples/with-google-analytics-amp",
"examples/with-google-analytics",
"examples/with-react-ga"preact関連
"examples/using-preact"サイトマップ関連
"examples/with-next-sitemap",
"examples/with-sitemap"既存プロジェクトからの移行関連
"examples/custom-routes-proxying"docker関連
"examples/with-docker"画像関連
"examples/image-component",
"examples/with-unsplash",
"examples/svg-components",
"examples/with-three-js"動画関連
"examples/with-hls-js",
"examples/with-mux-video",
"examples/with-videojs"アニメーション関連
"examples/with-gsap",
"examples/with-framer-motion"moved、removed、非推奨、廃止
"examples/page-transitions",
"examples/parameterized-routing",
"examples/with-cookie-auth",
"examples/with-dotenv",
"examples/with-firebase-authentication-serverless",
"examples/with-glamorous",
"examples/with-global-stylesheet-simple",
"examples/with-global-stylesheet",
"examples/with-markdown",
"examples/with-next-routes",
"examples/with-now-env",
"examples/with-pretty-url-routing",
"examples/with-sentry-simple",
"examples/with-strict-csp-hash",
"examples/with-styled-jsx-postcss",
"examples/with-sw-precache",
"examples/with-universal-configuration-build-time",
"examples/with-universal-configuration-runtime",
"examples/with-webpack-bundle-analyzer"古い、数年更新がない
"examples/with-reflux"その他
"examples/with-facebook-pixel",
"examples/with-mqtt-js",
"examples/with-msw",
"examples/with-paste-typescript",
"examples/with-portals-ssr",
"examples/with-portals",
"examples/with-service-worker",
"examples/with-cerebral",
"examples/with-custom-reverse-proxy",
"examples/with-expo-typescript",
"examples/with-expo",
"examples/with-flow",
"examples/with-monaco-editor",
"examples/with-next-offline",
"examples/with-next-seo",
"examples/with-orbit-components",
"examples/with-polyfills",
"examples/with-react-multi-carousel",
"examples/with-react-native-web",
"examples/with-react-toolbox",
"examples/with-reasonml-todo",
"examples/with-reasonml",
"examples/with-route-as-modal",
"examples/with-segment-analytics",
"examples/with-stencil",
"examples/with-stomp",
"examples/with-strict-csp",
"examples/with-stripe-typescript",
"examples/with-web-worker",
"examples/with-webassembly",
"examples/with-why-did-you-render",
"examples/with-xstate",
"examples/with-yarn-workspaces",
"examples/with-zeit-fetch"