とーますメモ

Ruby on Rails / Goなどの学習メモ

SSL更新作業について

自分用のメモ書き。SSLは引き続きNamecheapを使用。

thoames.hatenadiary.jp

SSL再発行のお知らせがメールで届くので、メール内のリンクから再発行の手続きを開始する。

1) CSR(証明書発行要求: Certificate Signing Request) の再作成

以前のCSRを使用すると、セキュリティ的に良くないため
新しいCSRを作成する。

2) ドメイン認証の認証方法を選択

CNAMEをDNSに設定して認証をパスする。

3) 確認画面

問題なければ、Submitを押すとメールで詳細が送られてくる。

4) メールの添付ファイルを確認

添付ファイルを解凍し、前回の同じやり方でファイルを統合した後、
nginxのファイルパスを変えて、再起動したらOK
thoames.hatenadiary.jp

Homebrewで特定のパッケージのみアップデートする場合

# 更新可能なformulaの一覧
brew outdated

# インストール済formulaの一覧
brew list

# Homebrew自体のアップデート
brew update

# インストール済みのすべてのパッケージをアップデート
brew upgrade

# 特定のパッケージのみアップデート
brew upgrade パッケージ名

[参考]
brewコマンド #brew - Qiita
【Homebrew】コマンド一覧 #homebrew - Qiita

【GAS】claspで開発環境を作る

今回は既に既存プロジェクトがあり、その内容をコピーして環境を作成することを前提にする。

1. 準備

1-2. Node.jsのインストール

今回はVoltaを使用してNode.js環境を作った。

1-3. プロジェクト用ディレクトリの作成

project_path内直下ではgit系のファイルなどが入るため、project_path内で更にsrcディレクトリを作成し、純粋なソースコードはこの中で管理する。

$ mkdir [project_path] & cd [project_path]
$ mkdir src

2. clasp環境設定

以下のコマンドでclasp及びtypescirpt系のパッケージをインストールする

$ npm init -y
$ npm install @google/clasp -g
$ npm install @types/google-apps-script


以下のコマンドでclasp経由でプロジェクトへログインする

$ clasp login

ブラウザが開くので、認証すればOK

新規で作成する場合は、以下コマンドでプロジェクトを作成するが

$ clasp create

既存プロジェクトがある場合は、以下コマンドでプロジェクトをcloneする。

$ clasp clone [script-id]

cloneすると.clasp.jsonができるので、ファイル内のrootDirをsrcに向けた後、
.clasp.json以外のファイルを一回消せば、これ移行push/pullするときはsrcファイル内のデータを対象にしてpush/pullするようになるので便利

$ clasp pull
$ clasp push


[参考]
GAS のGoogle製CLIツール clasp - Qiita
claspを使ってGoogle Apps Scriptの開発環境を構築してみた | DevelopersIO

【Next.js】Apollo Queryの返り値を元に、新しいデータを非同期で取得する場合

ちょっとハマったので、自分のメモ用。

以下のissueにかかれていたことを元にして解決。
github.com

上記の内容をカスタムフックにラップすればOK

const { loading, data, error } = useQuery(SOME_QUERY)
const [state, setState] = React.useState([])

React.useEffect(() => {
  // do some checking here to ensure data exist
  if (data) {
    // mutate data if you need to
    setState(data)
  }
}, [data])

年月のみを入力した場合、その月の最終日を自動補完する方法

年月のみが入力されたときも、当月の最終日を自動補完するコードを作った。

ex) A1に年月または年月日が入力される前提

TEXT(IF(LEN(A1)=7, EOMONTH(A1, 0), C2:C), "YYMMDD")

2022/06 => 220630
2022/06/20 => 220620

ポイントはLEN関数の長さが7の場合で、年月判定している箇所。
他にも年月判定する方法があるかもしれないが、これでとりあえずは対応できる。

※ EOMONTHの第2引数を0にすると当月の最終日が取得できる

TypeScriptで簡易Sprintfを作成する

Validationメッセージなどのメッセージには決まった文言が入るが、一部を置き換えたい場合などは、テンプレートリテラルよりC言語系で使われるSprintfが便利なのだが、JavaScriptにないため自作した。

export const sprintf = (format: string, ...args: string[]): string => {
  return format.replace(/{(\d+)}/g, (_match, index) => {
    return args[index];
  });
};

sprintf('{0}を入力してください', '名前')
=> '名前を入力してください'

[参考]
javascript - Convert JS sprintf to Typescript equivalent - Stack Overflow
Is there a sprintf equivalent for node.js - Code Examples

React Hook Form v7 × Material UIを使用したときのメモ書き

React Hook Formを使用するのは初めて。
React Hook Formを使用することでform内の値を管理するstateが不要になり、バリデーション機能も含まれているため、コード量を大幅に減らすことができる。またネット上にサンプルも非常に多いのも魅力的。

form値の監視や、他のUIライブラリとも組み合わせるのも可能。

React Hook Form ファーストインプレッション

v7について

React Hook Formはv7では書き方が以前のバージョンとは違っている。
ちなみに公式の説明はこちら
Migrate From V6 to V7 | React Hook Form - Simple React forms validation

register関数の使い方
- <input ref={register({ required: true })} name="test" />
+ <input {...register('test', { required: true })} />

スプレッド構文を使用することでシンプルに記述できるようになった。
以下が影響が大きそうな部分。

Controller
- <Controller as={<input />} />
+ <Controller render={({ field }) => <input {...field} />}

- <Controller render={(props, meta) => <input {...props} />} />
+ <Controller render={({ field, fieldState }) => <input {...field} />} />

as属性は廃止になり、代わりにrender属性をv7からは使用する。
render属性はfieldとfieldStateを含むオブジェクトを返す。

errros
- const { errors } = useForm();
+ const { formState: { errors } } = useForm();

errorsオブジェクトはfromStateオブジェクト内に属することになった。

実装時に困ったこと

Select要素のラベル表示にすごく困った。
React Hook FormとMaterial UIを併せたSelectのサンプルを紹介しているサイトは結構あるけど、v7のやり方でやってる例が意外となく、Material UIのform独特なかっこいいラベルのUIが、うまく動作しないという問題が発生した。

結論から言うと、以下のサイトさんを参考にし
React 初心者が Material-UI で今どきの Web フォームを作ってみた(react-hook-form編) | DevelopersIO

Controller内にTextFieldを入れて、Textfieldにselect属性をつけることで
Material UIのあのかっこいいUI効果があるラベルが実装できた。

<Controller
  name="sample_select"
  control={control}
  defaultValue={"default value"}
  render={({ field }): JSX.Element => (
    <TextField {...field} fullWidth size="small" select label={"Sample Select"}>
      {options.map((v) => (
        <MenuItem key={v.name} value={v.id}>
          {v.name}
        </MenuItem>
      ))}
    </TextField>
  )}
/>


[参考]
Using Material UI with React Hook Form - LogRocket Blog