YSNHatenaBlog

主にアプリやWebサービス開発について

reduxのデバッグ・リファクタリング

redux-dev-tools入れた

https://github.com/zalmoxisus/redux-devtools-extension

import { devToolsEnhancer } from 'redux-devtools-extension/developmentOnly'
import { createFirestoreInstance, firestoreReducer } from 'redux-firestore'

const initialState = {}
const rootReducer = combineReducers({
  firebase: firebaseReducer,
  firestore: firestoreReducer,
})
const store = createStore(rootReducer, initialState, devToolsEnhancer({}))

Command + Shift + Eで起動。便利だ。

f:id:yosuke403:20210202055023p:plain

react-redux-firebaseのStoreに型がつくようになる。重要。 https://qiita.com/Takepepe/items/6addcb1b0facb8c6ff1f

import 'react-redux'

import { FirebaseReducer, FirestoreReducer } from 'react-redux-firebase'

export interface State {
  firebase: FirebaseReducer.Reducer<
    unknown,
    Record<string, Record<string | number, string | number>>
  >
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  firestore: FirestoreReducer.Reducer
}

declare module 'react-redux' {
  // eslint-disable-next-line @typescript-eslint/no-empty-interface
  interface DefaultRootState extends State {}
}

Material-UIのフォーム完成 & Firestoreへの登録

座標が取得できたときに、formikのsetValueで値を更新したらラベルと値が重なってしまう。 本当は初期値nullにしたかった

面数はSelectより type="number" の方がいいな...せっかく調べたが。 とりあえず入力画面こんな感じでできた。MVP。

f:id:yosuke403:20210129061213p:plain

firestoreへの追加。関係あるところだけ。

import { useFirestore } from 'react-redux-firebase'

const NewCourt: React.FC<Record<string, unknown>> = () => {
  const firestore = useFirestore()

  const formik = useFormik({
    ...
    onSubmit: async (values, { setSubmitting }) => {
      const data: Omit<Court, 'id'> = {
        address: values.address,
        price: values.price,
        nighter: values.nighter,
        surfaces: {},
        name: values.name,
        createdAt: firebase.firestore.Timestamp.now(),
        geo: new firebase.firestore.GeoPoint(values.latitude, values.longitude),
        url: values.url,
      }
      try {
        const ref = await firestore.collection('courts').add(data)
        router.push(`/courts/${ref.id}`)
      } catch (e) {
        alert(e)
      }
      setSubmitting(false)
  }
  ...
}

住所からジオコードを取得

クライアントサイドはGeocoding API使えそう。 https://developers.google.com/maps/documentation/javascript/geocoding

ライブラリ。TypeScript対応。Geocoding API対応。 https://www.npmjs.com/package/@googlemaps/google-maps-services-js TypeScript対応。Geocoding API対応。

API有効化。restrictionに設定。

403エラー。

{
   "error_message" : "API keys with referer restrictions cannot be used with this API.",
   "results" : [],
   "status" : "REQUEST_DENIED"
}

リファラ付きだと駄目らしいので別APIキーつくる。

f:id:yosuke403:20210128062326p:plain

これで取得できた。

material-uiのSelect

Selectが切り替わらない。Controlledにするとだめ。 TextFieldは大丈夫なんだけどな...

TextFieldで書いてもいいらしい。見た目も綺麗なのでこっちで。

<TextField id="select" label="Age" value="20" select>
  <MenuItem value="10">Ten</MenuItem>
  <MenuItem value="20">Twenty</MenuItem>
</TextField>

そもそもFormControlとは?

Provides context such as filled/focused/error/required for form inputs. Relying on the context provides high flexibility and ensures that the state always stays consistent across the children of the FormControl. This context is used by the following components: - FormLabel - FormHelperText - Input - InputLabel

上のコンポーネントに入力状態を与えるもの、という感じだろうか。

TypeScriptでの連番配列の作り方

Array.from(Array(10).keys())

「オムニ」は「全天候」という意味らしい。

Selectはvalueにtouchedを入れないと反映されないな...。とりあえずこれで。

<TextField
    error={
      formik.touched.surfaceOmni &&
      formik.errors.surfaceOmni !== undefined
    }
    id="surface-omni"
    label="人工芝面数"
    value={formik.touched.surfaceOmni && formik.values.surfaceOmni}
    helperText={formik.touched.surfaceOmni && formik.errors.surfaceOmni}
    onChange={formik.handleChange}
    onBlur={formik.handleBlur}
    className={classes.select}
    select
    >
    {Array.from(Array(surfaceMax + 1).keys()).map((num) => (
      <MenuItem key={`surface-omni-${num}`} value={num}>
        {num}
      </MenuItem>
    ))}
</TextField>

とりあえず選べるようになった。

※ 2021/01/28 訂正 これだとタッチするまでControlled Componentじゃなくなってしまうので、修正

 <TextField
    error={
      formik.touched.surfaceOmni &&
      formik.errors.surfaceOmni !== undefined
    }
    id="surface-omni"
    label="人工芝面数"
    value={formik.values.surfaceOmni}
    helperText={formik.touched.surfaceOmni && formik.errors.surfaceOmni}
    onChange={formik.handleChange}
    onBlur={formik.handleBlur}
    className={classes.select}
    name="surfaceOmni"
    select
>
    {Array.from(Array(surfaceMax + 1).keys()).map((num) => (
      <MenuItem key={`surface-omni-${num}`} value={num}>
        {num}
      </MenuItem>
    ))}
</TextField>

f:id:yosuke403:20210127055359p:plain
tennico

2021年目標

子供が泣くので朝活できないから、今年の目標でも書いてみる。

 

とりあえずやりかかっている個人PJを完了させてしまうのと、最近知識の定着を意識してインプットしたいと思ってたので、本を読んで満足して終わらないよう、認証資格を目標に置いてみようかと思う。

 

こんな感じで↓

・Tennico Webのリリース
・Tennico iOSのリリース
GCP Associated Cloud Engineer
GCP Professional Cloud Architectの取得


参考
https://future-architect.github.io/articles/20190530/
https://qiita.com/mksamba/items/67ea80dec1dbb1d9692d

material-uiのtable修正&cssの改行

tableうまくいってないので修正。

TableCellの改行がされてなさそう。 TableContainerが不要そうだったので外しつつ、table自体にmin-width指定してたのを外す。

const useStyles = makeStyles({
-  table: {
-    minWidth: 650,
+  labelCell: {
+    wordBreak: 'keep-all',
+  },
+  valueCell: {
+    whiteSpace: 'normal',
+    wordBreak: 'break-word',
   },
 })

CSSの改行まわり整理

  • whiteSpace - 改行やスペース・タブをそのまま表示するか、無視するかを指定。
  • wordBreak - 改行するかを判断
  • overflowWrap - 改行するかを判断
  • wordWrap - overflowWrapと同じだが、サポートしてないブラウザがあるため併記するらしい?(https://w3g.jp/blog/confusing_word-break_word-wrap)

wordBreakとoverflowWrapの使い分け。

https://developer.mozilla.org/ja/docs/Web/CSS/overflow-wrap

メモ: word-break とは対照的に、 overflow-wrap は単語全体があふれずに行内に配置できない場合にのみ、改行を生成します。

なるほど。word-breakはあふれずに配置できても改行させるかを判断できるものということ。 今回だとあふれた場合だけ改行してほしいので、overflow-wrapを使うのが正しそう。 URLがwrapされないのでその場合はoverflow-wrap: anywhereにしてみる。

rel="nofollow" リンク先に評価を渡したくないときなどに使う。ユーザが投稿できるリンクには置いたほうがよさそう。 https://mightyace.co.jp/2020/07/15/column41/

sponsored, ugcというのができたらしい。