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

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

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

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

Material-UI

Material-UIは、Material Designを利用可能なオープンソースのReact向けUIコンポーネントキットです。

React.js

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

Q&A

解決済

1回答

6519閲覧

Material-ui/マルチセレクトのチェックボックスとセレクトの値が同期できない

moro123

総合スコア18

Redux

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

Material-UI

Material-UIは、Material Designを利用可能なオープンソースのReact向けUIコンポーネントキットです。

React.js

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

0グッド

0クリップ

投稿2019/05/06 04:17

編集2019/05/06 04:19

React/Redux/ReduxFormの構成でUIはMaterial-uiを使ってフォームを作成しています。
マルチセレクトのところで新規登録は問題ないのですが、一度登録した情報をGETで取得してから
セレクトで複数のユーザー名が表記されクリックしてチェックボックスをトグルで切り替え
して値(配列)の更新をしたいのですが、チェックボックスのon/offができません。

マルチセレクト:https://material-ui.com/demos/selects/#multiple-select

stateの流れですが、
(1) 親コンポーネントでGETした情報をpropsで渡し、子のコンポーネントで受け取ったpropsを
コピーしてSelectやCheckBoxの状態管理用の変数に代入してに初期化
(2) 初期化すると登録されてるユーザー名が表記され、changeイベントでチェックボックスをon/off切り替えて変更したいのですが、
配列の値がうまく更新されず、チェックも外れない状態になっています。
(3) 更新できたらチェックボックスの値をRedux-Formのprops.changeでformValueにセットしてpostする

問題はSelectとCheckBoxのそれぞれのコンポーネントで変数(selectedUser)の配列が同期されないので更新ができていないようです。
色々試してみましたが、期待通りの動きになりませんでした。
何か良い方法がありましたら、ご教授いただけると助かります。

■Parent.js(親) import React from 'react'; import { connect } from 'react-redux'; import { reduxForm } from 'redux-form'; import { withStyles } from '@material-ui/core/styles'; import ChildForm from '@/components/ChildForm'; const setInitial = apiData => { let initialValues = {}; Object.keys(apiData).forEach(key => { let value = apiData[key]; switch (key) { case 'multiple_select': let targetUserId = []; if (value && value.length > 0) { for (let val of value) { targetUserId.push(val.id); value = targetUserId; } } break; } initialValues[key] = value; }); return initialValues; }; class Parent extends React.Component { constructor(props) { super(props); } render() { const { initialValues } = this.props; const multipleOptions = [ { value: 1, label: 'A氏' }, { value: 2, label: 'B氏' }, { value: 3, label: 'C氏' } ]; return ( <div className={classes.root}> <ChildForm multiple_select={initialValues.multiple_select} multipleOptions={this.multipleOptions} /> </div> ); } } const mapStateToProps = state => { const getApiData = { multiple_select: [ { id: 1, name: 'A氏' }, { id: 2, name: 'B氏' }, { id: 3, name: 'C氏' } ] }; return { initialValues: setInitial(getApiData), multiple_form: state.form['multiple_form'] }; }; Parent = reduxForm({ form: multiple_form })(Parent); export default connect(mapStateToProps)(withStyles(styles)(Parent));
■ChildForm.js(子) import React from 'react'; import { connect } from 'react-redux'; import { reduxForm, reset } from 'redux-form'; import { withStyles } from '@material-ui/core/styles'; let selectedUser = []; → SelectやCheckboxの状態管理をするための変数 class ChildForm extends React.Component { constructor(props) { super(props); } // propsをコピーしてselectでユーザー名を表示させる componentWillReceiveProps() { if (this.props.multiple_select && this.props.multiple_select.length > 0) { selectedUser = [...this.props.multiple_select]; } } handleChangeSelect = event => { let getUser = event.target.value; selectedUser = [...getUser]; this.props.change([ { name: 'multiple_select', value: selectedUser } ]); }; render() { const { form, multiple_select, multipleOptions } = this.props; return ( <Paper> <FormControl> <InputLabel htmlFor="multiple-checkbox">マルチセレクト</InputLabel> <Select multiple displayEmpty value={selectedUser} onChange={this.handleChangeSelect} input={<Input id="multiple-checkbox" />} renderValue={selectedUser => { let selectedConvertName = []; if (selectedUser.length > 0) { for (let option of multipleOptions) { if (selectedUser.includes(option.value)) { selectedConvertName.push(option.label); } } } else { return '選択してください'; } return selectedConvertName.join('、 '); }} > {multipleOptions.map(option => { return ( <MenuItem key={option.value} value={option.value}> <Checkbox color="primary" checked={selectedUser.includes(option.value)} /> <ListItemText primary={option.label} /> </MenuItem> ); })} </Select> </FormControl> )} </Paper> ); } } const mapStateToProps = state => { return { multiple_form: state.form.multiple_form }; }; ChildForm = reduxForm({ form: state.form.multiple_form })(ChildForm); export default connect(mapStateToProps)(withStyles(styles)(ChildForm));

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

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

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

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

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

guest

回答1

0

ベストアンサー

いくつか確認していただきたいのですが、

問題の

マルチセレクトのチェックボックスとセレクトの値が同期できない

を操作した際に

① reduxのdev-toolsでstoreの値が変わっているか

yes: storeへの反映はできている
no: storeへ反映されていない

この辺が怪しくなりますね。

handleChangeSelect = event => { let getUser = event.target.value; selectedUser = [...getUser]; this.props.change([ { name: 'multiple_select', value: selectedUser } ]); };

② reactのdev-toolsでSelectコンポーネントのpropsのvalueの値は変わっているか

yes: Selectコンポーネントのドキュメントを見てみる(値は正常に流れている)
no: selectedUserという変数?が悪さをしていそう

value={selectedUser}あたりが怪しくなりますね。

<Select multiple displayEmpty value={selectedUser}

④ なんとなく、原因になっていそうな箇所

let selectedUser = []; → SelectやCheckboxの状態管理をするための変数

stateではだめでしょうか?

const setInitial = apiData => { let initialValues = {}; Object.keys(apiData).forEach(key => { let value = apiData[key]; switch (key) { case 'multiple_select': let targetUserId = []; if (value && value.length > 0) { for (let val of value) { targetUserId.push(val.id); value = targetUserId; } } break; } initialValues[key] = value; }); return initialValues; }; ... // propsをコピーしてselectでユーザー名を表示させる componentWillReceiveProps() { if (this.props.multiple_select && this.props.multiple_select.length > 0) { selectedUser = [...this.props.multiple_select]; } }

redux-formを使う場合、ここまで複雑なコードを書く必要がない覚えがあります。

投稿2019/05/07 07:50

odyu

総合スコア548

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

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

moro123

2019/05/10 01:24

コメントありがとうございます。 原因は`let selectedUser = []; → SelectやCheckboxの状態管理をするための変数` ここでした。 仰た通りにredux-formのstateに変更しましたら、マルチセレクトのチェックボックスとセレクトの値が同期できました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問