質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Redux

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

1回答

2128閲覧

【React,Redux,TypeScript】useSelectorで抽出したstateがundefindeになりtodoアプリが作れない。

webnakada

総合スコア7

Redux

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2020/11/14 10:47

簡単なtodoアプリを作成しようとしていますが、つまずいて前に進めなくなりました...
下記のように、taskとidのまとまりを一つのtodoとして、

TypeScript

1 type Todo = { 2 task: string, 3 id: number 4 } 5 6 type TodoState = { 7 todos: Todo[]; 8 }

それを配列の形でstateとして扱うようにして、その配列をmapメソッドで展開してUI上に表示させようと考えていましたが、書きのエラーメッセージが出て、表題のとおりstateがundefinedになってしまいます。

TypeError: Cannot read property 'map' of undefined

原因がどこにあるかわからず困っています。4ファイル分のコードを共有するので問題点などご指摘頂けると幸いです。

osなどの環境は下記の通りです。
OS macOS 10.15.7

"react": "^17.0.1", "react-dom": "^17.0.1", "react-hook-form": "^6.11.0", "react-redux": "^7.2.2", "react-scripts": "4.0.0", "redux": "^4.0.5", "typescript": "^4.0.3",

node.js 14.13.1

コード

App.tsx

useSelectorの2つの型引数としては、1つ目にはReducerの引数stateの型を渡し、2つ目にはuseSelectorで抽出する値の型を指定しています。

import React from 'react'; import { useForm } from 'react-hook-form'; import { useDispatch,useSelector } from 'react-redux'; import { add } from './action'; import { Todo,TodoState } from './reducer'; import './App.css'; export type InputText = { task: string; } function App() { const { register,handleSubmit,reset } = useForm(); const todos = useSelector<TodoState,Todo[]>((state)=>state.todos); const dispatch = useDispatch(); const onSubmit = (data: InputText): void => { const {task} = data; dispatch(add(task)); reset() }; return ( <> <form onSubmit={handleSubmit(onSubmit)}> <input name="task" ref={register}/> <input type="submit"/> </form> <ul> { todos.map((t) => { return( <li key={t.task}>{t.task}</li> ) }) } </ul> </> ); } export default App;

reducer.ts

型TodoStateをTodo[]として、Reducerの返り値の型に設定すれば、stateが配列として返ってくるという認識でしたが、うまくいきません。

●気になっていること
下記のコードのswitch文のcase Type.Addのreturn文の部分で、波括弧{}でオブジェクトの形式で書いていますが、「配列かえすなら角括弧[]使わないとな...)と思い、波括弧の代わりに角括弧を使い、配列の形式にするとエラーが出てしまいます。

※idはtodoを配列としてstateに追加していき、それの長さに応じて割り振りを行おうと思っていたのですが、表題の通りstateがundefinedとして返ってきたので実装できていません。ここではエラーが出ないように?をつけています。

import { Reducer } from 'redux'; import { TodoAction, TodoActionType as Type } from './action'; export type Todo = { task: string, id?: number } export type TodoState = { todos: Todo[]; } export const initialState: TodoState = {todos:[{task:"",id:0}]}; export const todoReducer: Reducer<TodoState,TodoAction> = ( state: TodoState = initialState, action: TodoAction ): TodoState => { switch (action.type) { case Type.ADD: return { ...state, ...action.payload } default:{ const check: never = action.type return check } } };

index.tsx

import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import { createStore } from 'redux'; import { Provider } from 'react-redux'; import { todoReducer,initialState } from './reducer'; const store = createStore(todoReducer,initialState); ReactDOM.render( <React.StrictMode> <Provider store={store}> <App /> </Provider> </React.StrictMode>, document.getElementById('root') );

action.ts

export const TodoActionType = { ADD:'ADD' } as const; type ValueOf<T> = T[keyof T]; export type TodoAction = { type: ValueOf<typeof TodoActionType> payload:{ task: string } } export const add = (text: string): TodoAction => ({ type: TodoActionType.ADD, payload:{ task:text } })

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ts

1const check: never = action.type 2return check

ここが原因ですね。
reducerが受け取るActionにはreduxが発行するActionもあります。defaultには来ないことを期待したコードなのでしょうけれど、残念ながら来てしまうので、action.typeの値をstateとして返すコードになってしまっています。return state;にすると治るはずです。

投稿2020/11/15 00:45

kazatsuyu

総合スコア158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

webnakada

2020/11/15 01:32

ありがとうございます!治りました。 さらに、reducer.tsのreturn文を下記のように直すことで、stateにtodoが追加されるようになり、目指していた実装となりました。 ``` return { todos:[ ...state.todos, { ...action.payload } ] } ``` おっしゃるとおりdefaultには来ないのでreturnの後に何を書いても、今回の問題には関係ないだろうと思っていました。ていうかそこに問題があることすら考えもしませんでした。 >reduxが発行するActionもあります。 とのことですが、initialstateを返すときはdefault部分に来るという認識で大丈夫でしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問