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

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

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

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

Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

TypeScript

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

React.js

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

Q&A

解決済

2回答

1103閲覧

useSelectoreから取得したデータをuseStateにsetしたい

makoxti

総合スコア32

Redux

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

Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

TypeScript

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

React.js

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

0グッド

0クリップ

投稿2022/02/10 17:34

技術スタック

React, Redux ToolKit, TypeScript, Next.js

作りたいアプリ

他画面で入力した値をRedux ToolKitの機能を使って別の画面で表示する

解決したい事象

フロントエンド初学者です。
useSelectoreから取得したデータをuseStateにsetし、map処理で1行ずつ取り出そうとすると、エラーになってしまいます。

useStateの定義

let property: Property[] = []; const [users, setUser] = useState(property);

useSelectoreからデータの取得

以下の方法でuseSelectoreからデータを取得しています。
const storeState = useSelector((state) => state.stateManagement);
storeStateをコンソールに出力した結果がこちらです。
イメージ説明

Stateへset処理

setUser(storeState)

map処理

map処理を一部抜粋します。

{users.map((user) => { return ( <td className="py-4 px-6 text-sm font-medium text-gray-900 whitespace-nowrap dark:text-white"> {user.name} </td> )}

エラー内容

イメージ説明

ソースコード全体

ソースコードはGitHubにpushしております。
https://github.com/makoxty/next_ts_tailwindcss
事象に関係ありそうなファイルの説明をします。
ListBody.tsxが一覧画面を表示するためのファイルです。
今回のエラーはこのファイルで起きています。
Add.tsxがデータを入力する画面です。
なので流れとしては、localhost:3000にアクセスすると一覧画面が表示されます。
最初は何もデータがないので、テーブルのヘッダだけ表示されていて欲しいです。
ナビゲーションの 登録 リンクよりデータの登録画面へ遷移し、データを入力します。
入力完了後に登録ボタンを押下し、ナビゲーションの Home リンクを押下後、入力画面で入力したデータが一覧に表示されていてほしいです。

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

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

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

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

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

hoshi-takanori

2022/02/10 19:33

「useSelectorから取得したデータをuseStateにset」すると、useSelector で取得した値 (redux が持つ、single source of truth であるべき値) とは別に、ローカルの state ができて二重管理することになると思いますが…。
makoxti

2022/02/11 08:20

なるほどです。 useSelectorから取得したデータを一覧で表示するにはどのように実装すればよろしいでしょうか。 具体的には、useSelectorから取得したデータをmapで繰り返して処理する実装方法のイメージがつかないです。
hoshi-takanori

2022/02/11 11:15

ソースコード拝見しましたが、stateSlice.tsx で add した時に、配列への要素の追加になってないですね。 また、Add.tsx を見ると、そもそも state の扱い方の理解に問題がありそう…。
makoxti

2022/02/11 15:56

ソースコードを見て頂きありがとうございます。 なるほど、Stateの理解に問題があるのですね。 Stateも含め、ReactHooksでの開発方法の考え方の参考になるサイトや参考書等ご存知であれば教えて頂きたいです。
guest

回答2

0

自己解決

解答がこないためクローズ

投稿2022/02/13 10:17

makoxti

総合スコア32

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

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

0

添削してみます。

Property.ts

  • Property という型はユーザーを意味しているようなので、User にすると良いでしょう。
  • RootState という型名は redux が扱う state 全体を表すので、ここでは使いません。
    UsersState という名前にして、ユーザーの配列を持つようにすると良いでしょう。
  • これらは redux が扱う state の型なので、pages/components の下じゃない方が良い気が…。

ts

1export interface User { 2 name: string; 3 sex: string; 4 age: number; 5 hobby: string; 6 index: number; 7} 8 9export type UsersState = User[];

stateSlice.ts → usersSlice.ts

  • ユーザーの配列を扱う slice なので、usersSlice という名前にすると良いでしょう。
    この slice が持つ state はユーザーの配列、つまり UsersState (User[]) になります。
  • initialState に空文字列が入った要素を持たせるのは良くないですね。
    空の配列にして、as UsersState で型を指定すると良いでしょう。
  • アクション名は単なる add よりも addUser の方が分かりやすいような。
    また、action の型は PayloadAction を使って action.payload の型を指定しましょう。
  • addUser の引数 UserWithoutIndex は、User のうち index を含まないものです。
    参考: 【TypeScript】型定義の指定したプロパティのみ利用したい(Pick, Omit)
  • addUser では次の index を計算して、そのユーザーを追加した配列を返します。
  • replaceUsers はユーザーの配列をまるごと入れ替えるものです。

ts

1import { createSlice, PayloadAction } from "@reduxjs/toolkit"; 2import { User, UsersState } from "../interface/Property"; 3 4type UserWithoutIndex = Omit<User, "index">; 5 6export const usersSlice = createSlice({ 7 name: "users", 8 initialState: [] as UsersState, 9 reducers: { 10 addUser: (state, action: PayloadAction<UserWithoutIndex>) => { 11 const index = Math.max(0, ...state.map(user => user.index)) + 1; 12 return [...state, { ...action.payload, index }]; 13 }, 14 replaceUsers: (state, action: PayloadAction<UsersState>) => { 15 return action.payload; 16 }, 17 }, 18}); 19 20export const { addUser, replaceUsers } = usersSlice.actions; 21 22export default usersSlice.reducer;

store.ts

  • stateManagement ではなく users にしましょう。
  • RootState は redux が扱う state 全体の型、AppDispatch は dispatch の型になります。

ts

1import { configureStore } from "@reduxjs/toolkit"; 2import usersSlice from "./usersSlice"; 3 4export const store = configureStore({ 5 reducer: { 6 users: usersSlice 7 }, 8}); 9 10export type RootState = ReturnType<typeof store.getState>; 11export type AppDispatch = typeof store.dispatch; 12 13export default store;

Add.tsx

  • useState つまりこの画面に固有の state は、name, sex, age, hobby だけです。
  • ユーザー追加の際、新しい index は reducer で計算するので、ここでは不要になります。

tsx

1import React, { useState } from "react"; 2import { Layout } from "./Layout"; 3import Header from "./Header"; 4import { useDispatch } from "react-redux"; 5import { AppDispatch } from "../../redux/store"; 6import { addUser } from "../../redux/usersSlice"; 7 8const Add = () => { 9 const dispatch = useDispatch<AppDispatch>(); 10 11 const [name, setName] = useState(""); 12 const [sex, setSex] = useState(""); 13 const [age, setAge] = useState(0); 14 const [hobby, setHobby] = useState(""); 15 16 const handleChangeName = (e: any) => { 17 setName(e.target.value); 18 }; 19 20 const handleChangeSex = (e: any) => { 21 setSex(e.target.value); 22 }; 23 24 const handleChangeAge = (e: any) => { 25 setAge(parseInt(e.target.value) ?? 0); 26 }; 27 28 const handleChangeHobby = (e: any) => { 29 setHobby(e.target.value); 30 }; 31 32 const onClickButton = () => { 33 dispatch(addUser({ name, sex, age, hobby })); 34 }; 35 36 return ( 37 // 略 38 <button 39 type="button" 40 onClick={onClickButton} 41 // 略

ListBody.tsx

  • ユーザーの一覧を表示するだけなら、独自の state を持たないので、useState は不要です。

ts

1import Link from "next/link"; 2import React from "react"; 3import { useSelector, useDispatch } from "react-redux"; 4import { RootState, AppDispatch } from "../../redux/store"; 5import { replaceUsers } from "../../redux/usersSlice"; 6 7const ListBody = () => { 8 const users = useSelector((state: RootState) => state.users); 9 const dispatch = useDispatch<AppDispatch>(); 10 11 const dataInsert = () => { 12 const newUsers = [ 13 { 14 name: "一郎", 15 sex: "男", 16 age: 22, 17 hobby: "珈琲", 18 index: 1, 19 }, 20 { 21 name: "一子", 22 sex: "女", 23 age: 20, 24 hobby: "ピアノ", 25 index: 2, 26 } 27 ]; 28 dispatch(replaceUsers(newUsers)); 29 }; 30 31 return ( 32 // 略

投稿2022/02/13 07:11

編集2022/02/13 07:18
hoshi-takanori

総合スコア7895

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問