Redux typescript @yukilulu0229

## インストール typescript対応
https://redux.js.org/usage/usage-with-typescript

```
npm install @types/react-redux
```


## インストール redux
https://redux-toolkit.js.org/

```terminal
npm install @reduxjs/toolkit
```

```terminal
npm install react-redux
```

## 型定義
Type.tsを作る

```Type.ts
export interface InitialCurrentUserState {
  currentUser: null | {
    uid: string;
    photo: string;
    email: string;
    displayName: string;
  };
}

```

## storeを作る
https://redux-toolkit.js.org/api/configureStore#basic-example

```src/app/store.ts
import { configureStore } from "@reduxjs/toolkit";
import currentUserReducer from "../features/currentUserSlice.ts";

export const store = configureStore({
  reducer: currentUserReducer,
});

// https://zenn.dev/engstt/articles/293e7420c93a18
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;
//storeの現在の状態の型を取得
// getStateはアプリケーションの現在の状態ツリーを返します.これはstoreのreducerによって返された最後の値と同じす


```

## reducerを作る
https://redux-toolkit.js.org/usage/usage-with-typescript#createslice

```src/features/currentUserSlice.ts
import { createSlice } from "@reduxjs/toolkit";
import { InitialCurrentUserState } from "../Type.ts";

const initialState: InitialCurrentUserState = {
  currentUser: null,
};

export const currentUserSlice = createSlice({
  name: "currentUser", // 任意の名前を付けれる
  initialState: initialState,
  reducers: {
    login: (state, action) => {
      state.currentUser = action.payload;
    },
    logout: (state) => {
      state.currentUser = null;
    },
  },
});

export const { login, logout } = currentUserSlice.actions;

export default currentUserSlice.reducer;

```

## provider設定

```index or main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import { Provider } from "react-redux"; // 読み込む
import App from "./App.tsx"; 
import "./index.css";
import { store } from "./app/store.ts"; // 読み込む

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <Provider store={store}> // 囲む
      <App />
    </Provider> // 囲む
  </React.StrictMode>,
);

```


## useSelector

https://redux.js.org/usage/usage-with-typescript

```src/app/hooks.ts

import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import { AppDispatch, RootState } from "./store.ts";

export const useAppDispatch: () => AppDispatch = useDispatch;

export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

```

```App.tsx
import React, { useEffect } from "react";
import { useAppDispatch, useAppSelector } from "./app/hooks.ts";
import { login, logout } from "./features/currentUserSlice.ts";
import { auth } from "./firebase.ts";

function App() {
  const currentUser = useAppSelector((state) => state.currentUser);

  const dispatch = useAppDispatch();

  // auth.onAuthStateChangedはfirebaseの機能でユーザー情報が変わったら
  useEffect(() => {
    auth.onAuthStateChanged((loginUser) => {
      if (loginUser) {
        dispatch(
          login({
            uid: loginUser.uid,
            photo: loginUser.photoURL,
            email: loginUser.email,
            displayName: loginUser.displayName,
          }),
        );
      } else {
        dispatch(logout());
      }
    });
  }, [dispatch]);  //dispatchに変更があるごとに

  return (
    <div className="App">
      ...
    </div>
  );
}

export default App;


```