こんにちは
ひとつ押さえておくべきことは、リデューサーを書くとき、以下
javascript
1const TODOS = {
2 todos: ["デバッグ用", "その2"]
3};
のようにリデューサーの引数 state の初期値を書きますが、これはstateの初期値がこのような内容のものである(todosに["デバッグ用", "その2"]という確認用の文字列が入っている。)という情報以外にも、もう一点重要なことを伝えています。それは何かというと、リデューサー本体で return する値が
javascript
1{
2 todos: [ "文字列1", "文字列2", "文字列3", ... ]
3}
という形(TypeScript的にいえば型。以後、この回答でも型といいます。)のオブジェクトであるということです。その観点で確認すると
javascript
1case ADD_TODO:
2 console.log([...state.todos, action.value]); // [todos + 入力したvalue]
3 return [...state.todos, action.value];
の部分が正しくないことが分かります。上記では文字列の配列をreturnしており、初期値TODOS
と同じ型のオブジェクトを返していません。ですので、以下のように修正すると、意図通り動く(もしくは、現状で問題になっているエラーは解消される)と思います。
javascript
1return { ...state, todos: [...state.todos, action.value] };
追記1
javascript
1const TODOS = {
2 todos: ["デバッグ用", "その2"]
3};
の変数名は、TODOS
でもよいとは思いますが、INITIAL_STATE
だったり、 initialState
あるいは initState
といった、初期stateであることが分かる変数名にしたほうがよいかもしれません。それで例えば、 initialState
と書くと決めたら、別のリデューサーでも initialState
と書くことにすれば、コードが統一されて、全リデューサーの初期stateのコードを拾い出したいとき、 initialState
で検索すればよいことになります。
追記2
以下、参考までの補足です。
ReactとReduxによるアプリを書くのに、使う言語を JavaScript から TypeScriptに移行して、きちんと型を意識したコードを維持すると、
typescript
1return [...state.todos, action.value];
というコードを(うっかり)書いたとしても、リデューサーが返すべき値の型に合っていない旨のエラーとして警告されます。使っているエディタによっては、上記のようなコードを書くと、即、コードに赤の下線だったりが表示され、そこにマウスを乗せると、何が原因で型エラーになっているのかのエラーメッセージがホバーで表示されます。
ただし、nakamura0907さんの今の段階では、TypeScriptの習得はまだ先でよく、それよりもJavaScript でたくさん書いて、今回のようなエラーにたくさん遭遇するのがよいと思います。
追記3
現状のstateの型は
javascript
1const TODOS = {
2 todos: ["デバッグ用", "その2"]
3};
上記のように、文字列の配列todos
のみを持つオブジェクトなので、上記に回答した
javascript
1return { ...state, todos: [...state.todos, action.value] };
の ...state,
は不要で
javascript
1return { todos: [...state.todos, action.value] };
でも大丈夫ですが、今後、todos
以外にもプロパティが増えることが見えているのでしたら、
javascript
1return { ...state, todos: [...state.todos, action.value] };
と書いておけば、プロパティが増えても todos
だけが更新されて他のプロパティは同じ値で引き継がれたstateを返すコードになっています。
以上、参考になれば幸いです。