実現したいこと
Reduxのステートに格納してあるログイン時に取得したuserオブジェクトから、メールアドレスを抽出し、そのメールアドレスをキーとしてtokenDict内のトークンを取得したい。なお、ログイン時に格納したuserからはemailのみが必要なため、userInfoインターフェース内はemailのみとなっている。
発生している問題
問題としては、userEmailをtokenDictの引数として渡した際に、userInfoのインターフェース内のemailに?をつけなければ、"Property 'email' is missing in type '{}' but required in type 'userInfo'."というエラーが出てしまい、?をつけると"Property 'email' of type 'string | undefined' is not assignable to string index type 'string'."というエラーが出てしまっていて立ち止まっています。2つ目のエラーはオブジェクトのキーがundefinedを許すことはpropertyがemailのみということもあり、許されないことは理解しております。エラーとログイン時に返ってくるUserオブジェクトは以下のスクリーンショットの通りになります。
コード
Typescript
1//tokenDict.tsx 2export const tokenDict: { [email: string]: string } = { 3 "user1@example.com": "sample_token1", 4 "user2@example.com": "sample_token2", 5};
Typescript
1//HomeScreen.tsx 2interface userInfo { 3 email: string; //email vs email? 4 [key: string]: string; 5} 6const HomeScreen: React.FC = () => { 7 const user: userInfo = useGlobalState("user"); //user object returned from login process is stored in user state in Redux. 8 const userEmail: string = user.email; 9 const token = tokenDict[userEmail]; 10
TypeScript
1//App.tsx 2const App: React.FC = () => { 3 const user = useGlobalState("user"); 4 const dispatch = useDispatch(); 5 6 useEffect(() => { 7 const unsubscribe = auth.onAuthStateChanged((authUser) => { 8 if (authUser) { 9 dispatch({ 10 type: "SET_USER", 11 user: authUser, 12 }); 13 } else { 14 dispatch({ 15 type: "SET_USER", 16 user: {}, 17 }); 18 } 19 }); 20 return () => { 21 unsubscribe(); 22 }; 23 }, []); 24 25 return ( 26 <Router> 27 <div className="app"> 28 <Switch> 29 <Route path="/login"> 30 <Header /> 31 <Login /> 32 </Route> 33 <Route path="/"> 34 <Header /> 35 <div className="app__mainscreen"> 36 <ChatScreen /> 37 </div> 38 </Route> 39 </Switch> 40 </div> 41 </Router> 42 ); 43}; 44 45export default App; 46
TypeScript
1//reducer.tsx 2export const initialState = { 3 user: {}, 4}; 5export type State = typeof initialState; 6 7export type Action = { type: "SET_USER"; user: {} }; 8 9export const reducer = (state: State, action: Action) => { 10 switch (action.type) { 11 case "SET_USER": 12 return { 13 ...state, 14 user: action.user, 15 }; 16 default: 17 return state; 18 } 19}; 20 21export default reducer; 22
TypeScript
1//StateProvider.tsx 2import React, { createContext, useContext, useReducer } from "react"; 3import { Action, initialState, reducer, State } from "./reducer"; 4 5const stateContext = createContext(initialState); 6const dispatchContext = createContext((() => 0) as React.Dispatch<Action>); 7 8export const Provider: React.ComponentType = ({ children }) => { 9 const [state, dispatch] = useReducer(reducer, initialState); 10 return ( 11 <dispatchContext.Provider value={dispatch}> 12 <stateContext.Provider value={state}>{children}</stateContext.Provider> 13 </dispatchContext.Provider> 14 ); 15}; 16 17export const useDispatch = () => { 18 return useContext(dispatchContext); 19}; 20 21export const useGlobalState = <K extends keyof State>(property: K) => { 22 const state = useContext(stateContext); 23 return state[property]; 24};
補足情報
- TypeScript
- React
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/01/19 22:28 編集
2021/01/20 07:13
2021/01/21 00:41