🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Redux

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

React.js

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

Q&A

解決済

1回答

2323閲覧

State が変わらない問題 dispatch from react-hook-form

tajihiro

総合スコア14

Redux

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

React.js

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

0グッド

0クリップ

投稿2019/12/06 22:56

react-hook-formを使用して画面遷移をしようとしています。
今回react-hook-formを使用していることで、InputForm内にて、dispatch と setState 実行するべきだと考えています。dispatch はできたのですが、setStateがうまく行きません。

import React, { Component } from "react"; import { connect } from "react-redux"; import InputForm from "./inputForm"; import ConfirmForm from "./comfirmForm"; class Sample extends Component { constructor(props){ super(props); this.state = { mode: 'input' } } render() { switch (this.state.mode) { case 'input': return (<InputForm />); case 'confirm': return (<ConfirmForm />); default: return (<InputForm />); } } } export default connect((state)=>state)(Sample);
import React from 'react' import { connect } from "react-redux"; import useForm from 'react-hook-form' import {Link} from "react-router-dom"; function InputForm(props) { const { register, handleSubmit, watch, errors } = useForm(); const onSubmit = data => { console.log(data); props.dispatch({type: 'CONFIRM'}); }; return ( <div> <form onSubmit={handleSubmit(onSubmit)}> <label>Last Name:</label> <input type="text" name="last_name" ref={register}/> <label>First Name:</label> <input type="text" name="first_name" ref={register}/> <input type="submit" value="更新"/> </form> <Link to={"/"}>戻る</Link> </div> ); } export default connect((state)=>state)(InputForm);
const initData = { mode: 'input' } export function pageReducer(state = initData, action){ console.log('page04Reducer:TYPE: ' + action.type) switch (action.type) { case 'INPUT': return {mode: 'input'}; case 'CONFIRM': return {mode: 'confirm'}; default: return state; } }

とりあえず、コードを眺めてみて、ご指摘があるところがありますでしょうか?
問題点は、setState で、mode が更新できずに、Sample class の render内の制御がうまく行かないことです。

ご指摘お願いします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

こんにちは

フォームが入力の受付中であるか、または確認の表示中であるかという2状態を、redux state の mode というプロパティで保持させる意図と思われましたが、そうだとすると、Samplethis.state にも modeを重複して持つ必要はないと思われます。 this.statemode を持たせなくても、Sample では

javascript

1export default connect((state)=>state)(Sample);

によってreduxとconnectされることにより、this.props に redux の state が入ってきますので、これを使えばよいです。

この考え方にそって、下記にいくつかのSampleの修正版を挙げます。これらは、リデューサーがpageReducer しかなく、Reduxのstoreが以下

javascript

1const store = createStore(pageReducer);

によって作られていることを前提にしています。

sample.js (Sampleクラス修正版その1)

jsx

1import React, { Component } from "react"; 2import { connect } from "react-redux"; 3import InputForm from "./inputForm"; 4import ConfirmForm from "./comfirmForm"; 5 6class Sample extends Component { 7 render() { 8 switch (this.props.mode) { 9 case 'input': 10 return (<InputForm />); 11 case 'confirm': 12 return (<ConfirmForm />); 13 default: 14 return (<ConfirmForm />); 15 } 16 } 17} 18 19export default connect((state)=>state)(Sample); 20

または、this.stateを使わないので関数型コンポーネントで書いて

sample2.js (Sampleクラス修正版その2)

jsx

1import React from "react"; 2import { connect } from "react-redux"; 3import InputForm from "./inputForm"; 4import ConfirmForm from "./comfirmForm"; 5 6const Sample = ({ mode }) => { 7 switch (mode) { 8 case 'input': 9 return (<InputForm />); 10 case 'confirm': 11 return (<ConfirmForm />); 12 default: 13 return (<ConfirmForm />); 14 } 15} 16 17export default connect((state)=>state)(Sample); 18

さらに短いコードで済ませるとすれば、

sample3.js (Sampleクラス修正版その3)

jsx

1import React from "react"; 2import { connect } from "react-redux"; 3import InputForm from "./inputForm"; 4import ConfirmForm from "./comfirmForm"; 5 6const Sample = ({ mode }) => ( 7 mode === 'input' ? <InputForm /> : <ConfirmForm /> 8) 9 10export default connect((state)=>state)(Sample); 11 12

でも良いかと思います。
下記に動作確認用のサンプルを作りました。

これは、ご質問に挙げられているコードを転記して各ファイルを作成し、Sample については上記の各修正版を追加して、index.js と comfirmForm.jsは当方で適当に作成して補ったものです。

なお上記に挙げたコードは、冒頭に書いたとおり、リデューサーが pageReducer しかなく、

javascript

1const store = createStore(pageReducer);

によって storeを作っている想定のものですが、tajihiroさんの実際のコードでは、いくつかのリデューサーをcombineReducersしていると思います。その場合は、 各コンポーネントに入ってくる redux state から mode を取り出すために、もうひとつプロパティが必要になると思われます。そこは適宜、ご自身のコードに合わせて頂ければと思います。

具体的なコードの修正方法はさておき、この回答の主旨は、初めに書いたとおり

  • mode は Redux の state にあるのだから、Sample の this.state に重複して持つ必要は無いのでは?

ということになります

投稿2019/12/07 11:58

編集2019/12/07 14:38
jun68ykt

総合スコア9058

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

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

tajihiro

2019/12/09 01:21 編集

返信おくれました。アドバイスありがとうございます。 jun68yktさんのご指摘理解できました。その上で関数でなく元の`render()`で処理をしたい時に、`this.props.mode`が`undefined`になってしまいます。何かお気づきの点はございますでしょうか? 私のソースコードの不備であるとは思いますが。 ``` render() { switch (this.props.mode) ```
tajihiro

2019/12/09 01:40

一点、私の理解不足ですが、stateの`mode` というプロパティがあるのですね。これが少しややこしくしているようです。例えば、画面表示制御を別のプロパティで行う方が良いのでしょうか?
tajihiro

2019/12/09 02:44 編集

その他、`combineReducers` 等を使用しているのでそれらの影響はあるのでしょうか? >いくつかのリデューサーをcombineReducersしていると思います。 > その場合は、 各コンポーネントに入ってくる redux state から mode を取り出すために、もうひとつプロパティが必要になると思われます。
jun68ykt

2019/12/09 03:04

こんにちは すみません。 私の > もうひとつプロパティが必要になると思われます。 という書き方が悪かったと思います。 言いたかったことをコードで示します。 たとえばもし、pageReducerのほかに、itemReducer、 userReducer というリデューサーもあって、createStoreするときに、 const rootReducer = combineReducers({ page: pageReducer, item: itemReducer, user: userReducer }); const store = createStore(rootReducer); という感じで combineReducers しているとしたら、render でswitchするところが、 switch (this.props.mode) ではなく、 combineReducers で、pageReducer を指定しているキーの page を、 this.props と mode の間に追加して、 switch (this.props.page.mode) としなければならないと思います。 > もうひとつプロパティが必要になると思われます。 と書いたのは、 この例でいうと、this.props と mode の間に、 もうひとつ page を挟む必要があります、という意味でした。
tajihiro

2019/12/09 03:18

できました。とても助かりました。
jun68ykt

2019/12/09 03:23

> できました。 とのことで、よかったです????
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問