やるぶろ

なんでもやる。垂れ流す。汚いです。

Reduxとnormalizrを使う

normalizr

JSONを正規化するためのライブラリ

normalizr - npm

使い方が分かりづらい…

Reduxのドキュメントに色々書いてあるけど使い方が分かりづらい 特にJSONがネストされているとき
Normalizing State Shape | Redux

正規化されたデータの更新について読んで切る途中。 今日は頭が働かないな…
Updating Normalized Data | Redux

Reduxのセレクタ理解する

お題はTodoアプリ。

idとtitleを持つTaskの配列をstateで管理し、
指定したidのTaskのtitleをセレクタで取得するような処理を書きたい。

まずはざっくり画面を作る。

componentの構成はこんな感じ
Index
└App
 ┝Header
 └TaskList
  └TaskItem

一旦ルーティングやサーバー側の実装はなし。
stateの初期値と変更後の値でごちゃごちゃしてみよう。

TaskSlice.tsxはいろいろ省略してるけどこんな感じ!

export interface Todo {
    id: number
    title: string
    finished: boolean
}

export interface Task {
    id: number
    title: string
    todos: Todo[]
}

export const taskSlice = createSlice({
    name: 'tasks',
    initialState: [
        {
            id: 1,
            title: "task#1",
            todos: [
                {
                    id: 1,
                    title: "todo#1-1",
                    finished: true
                },
                {
                    id: 2,
                    title: "todo#1-2",
                    finished: false
                }
            ]
        },
        {
            id: 2,
            title: "task#2",
            todos: [
                {
                    id: 3,
                    title: "todo#2-1",
                    finished: false
                },
                {
                    id: 4,
                    title: "todo#2-2",
                    finished: false
                }
            ]
        }
    ] as Task[],
    reducers: {},
    extraReducers: {}
})

export default taskSlice

動作確認のためRedux DevToolsを入れる

初期値がStateに入ってる! f:id:momoshima:20211014074115p:plain

ここから、Taskのidを指定するとidが一致するTaskを返すようなメソッドを作りたい
これみながらやる

redux.js.org

セレクター関数には2種類ある * Sliceファイル内に関数として定義 * コンポーネントファイル内で使うuseSelector()

const data = useSelector(state => state.some.deeply.nested.field)

useSelectorを使って上記のような書き方もできるけど設計的にはよろしくない
コンポーネントに同じような記述があると、stateの構造を変更した場合の影響が大きいから レデューサー関数とセレクタのみがstateの構造を知っている必要がある(メモ化というらしい)

メモ化するためにRedux ToolkitパッケージのcreateSelector()を使う

使い方はこんな感じ(公式より)

const selectA = state => state.a
const selectB = state => state.b
const selectC = state => state.c

const selectABC = createSelector([selectA, selectB, selectC], (a, b, c) => {
  // do something with a, b, and c, and return a result
  return a + b + c
})

// Call the selector function and get a result
const abc = selectABC(state)

// could also be written as separate arguments, and works exactly the same
const selectABC2 = createSelector(selectA, selectB, selectC, (a, b, c) => {
  // do something with a, b, and c, and return a result
  return a + b + c
})

自分が使いたいのはこんな感じ?

const selectItems = state => state.items
const selectItemId = (state, itemId) => itemId

const selectItemById = createSelector(
  [selectItems, selectItemId],
  (items, itemId) => items[itemId]
)

selectItemsselectItemIdが入力セレクタ
selectItemByIdが出力セレクタかな?

ReactアプリにTailwind CSSを適用する

23:50
こんな時間だけどやる気が出たのでReduxのセレクタを理解していきたい。

お題はTodoアプリ。

idとtitleを持つTaskの配列をstateで管理し、
指定したidのTaskのtitleをセレクタで取得するような処理を書きたい。

まずはざっくり画面を作る。

componentの構成はこんな感じ
Index
└App
 ┝Header
 └TaskList
  └TaskItem

一旦ルーティングやサーバー側の実装はなし。
stateの初期値と変更後の値でごちゃごちゃしてみよう。

Tailwind CSSを入れる

公式さん
Tailwindが入らない〜

$ npx tailwindcss-cli@latest init
npx: installed 141 in 21.035s
Invalid or unexpected token
(node:1648) ExperimentalWarning: The fs.promises API is experimental

nodeのバージョンが古いかも?
参考

アップデートしました。
参考 - Option2

お次は@tailwindが解決しない
f:id:momoshima:20211014004838p:plain

craco.config.jsがroot直下にないだけだった。
srcの下に作っちゃってた。

スタイルが適用されるようになった!

   

React-Reduxのアプリが上手くrunできなかったので色々頑張った

アプリをReduxとか入れて少し画面を作ってみたらnpm startできなくなった

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! redux20211011@0.1.0 start: `react-scripts start`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the redux20211011@0.1.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

ESLintのparserを導入

ESLintの方でエラーが出てた。

Failed to load parser '@typescript-eslint/parser' declared in 'package.json » eslint-config-react-app#overrides[0]': Cannot find module 'typescript'

parser入れるの忘れてたわ。

npm i --save-dev typescript @typescript-eslint/parser

react-domの導入

react-domも入れるの忘れてた。

npmのサイトではインストール用コマンドが https://www.npmjs.com/package/react-domになってるけど
`npm i --save-dev @types/react-domの方で成功した。

tsのエラー解決やGitへのコミットのためにごちゃごちゃ

TS17004: Cannot use JSX unless the '--jsx' flag is provided.

tsconfig.jsonに設定を追加する

{
  "compilerOptions": {
    "jsx": "react-jsx",
  }
}

Gitにpushする

いつもお世話になっているこの記事を参考にやっていく。

最初のcommit messageは多分こんな感じ?

Initial commit

f:id:momoshima:20211012084605p:plain

参考

https://qiita.com/hrism/items/3dff3f7822bb36e414a8