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

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

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

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

React.js

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

Q&A

解決済

1回答

2673閲覧

ReduxでPropsを変更したのにも関わらずrenderで反映されない

tojima

総合スコア16

Redux

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

React.js

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

0グッド

0クリップ

投稿2019/06/01 08:45

rootReducer

1const initState = { 2 todos: [ 3 {id: 1, title: 'test1', content: 'content1', done: false}, 4 {id: 2, title: 'test2', content: 'content2', done: true} 5 ] 6} 7 8const rootReducer = (state = initState, action) => { 9 switch (action.type) { 10 case 'DONE_TOGGLE': 11 let index = state.todos.findIndex((todo) => todo.id === action.id) 12 state.todos[index].done = !state.todos[index].done 13 return { 14 todos: [...state.todos] 15 } 16 } 17 return state 18} 19 20export default rootReducer;

Dashboard

1import React from 'react' 2import { Link } from 'react-router-dom' 3import { connect } from 'react-redux' 4import TodoSummary from '../todos/TodoSummary' 5 6const Dashboard = ({todos}) => { 7 return ( 8 <div className="container dashboard"> 9 <h2 className="indigo-text darken-4">ALL TASKS</h2> 10 <div className="dashboard-links"> 11 <Link to='/' >全て</Link> 12 <Link to='/finish' >完了</Link> 13 <Link to='/notfinish' >未完了</Link> 14 </div> 15 { todos && todos.map(todo => { 16 return ( 17 <TodoSummary todo={todo} key={todo.id}/> 18 ) 19 })} 20 </div> 21 ) 22} 23 24const mapStateToProps = (state, ownProps) => { 25 console.log(ownProps) 26 return { 27 todos: state.todos 28 } 29} 30 31export default connect(mapStateToProps)(Dashboard);

TodoSummary

1import React from 'react' 2import { connect } from 'react-redux' 3import { deleteTodo, doneToggle } from '../store/actions/todoActions' 4 5class TodoSummary extends React.Component{ 6 handleClick = (id) => { 7 this.props.deleteTodo(id) 8 } 9 handleToggle = (id) => { 10 this.props.doneToggle(id) 11 } 12 render() { 13 const { todo } = this.props 14 return ( 15 <div className="row todosummary"> 16 <div className="col s12"> 17 <div className="card blue-grey darken-1"> 18 <div className="card-content white-text"> 19 <span className="card-title">{ todo.title }</span> 20 <p>{ todo.content }</p> 21 </div> 22 <div className="card-action"> 23 <span className="waves-effect waves-light btn delete-btn" onClick={() => (this.handleClick(todo.id))}>DELETE TASK</span> 24 {todo.done ? <a className="waves-effect waves-light btn lime" onClick={() => (this.handleToggle(todo.id))}>未完了にする</a> : <a className="waves-effect waves-light btn orange" onClick={() => (this.handleToggle(todo.id))}>完了にする</a>} 25 </div> 26 </div> 27 </div> 28 </div> 29 ) 30 } 31} 32 33const mapDispatchToProps = (dispatch) => { 34 return { 35 deleteTodo: (id) => dispatch(deleteTodo(id)), 36 doneToggle: (id) => dispatch(doneToggle(id)) 37 } 38} 39 40 41export default connect(null, mapDispatchToProps)(TodoSummary);

「完了する」もしくは「未完了する」ボタンがクリックされるとreduxのstoreの該当するTodoのdoneがtrue、falseとなるようにしました。

他のコンポーネントではうまくいくのですが、このDashboardからtodoSummaryではうまくいっていません。

また確認としてconsole.log(state.todo.done)をクリックされた時に確認しますと、うまくtrueとfalseが変わっています。

これはどういったことが原因でrenderに反映されていないのでしょうか?

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

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

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

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

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

guest

回答1

0

ベストアンサー

こんにちは

state.todos の中の変更対象になる要素について、単に done をトグルするだけではなく、 新しいオブジェクトにする必要があります。

ですので、ご質問にあるコードに最小限の変更で、とりあえずトグルした done で再render させるには、たとえば以下のように修正してみるといかがでしょうか?

修正前:

javascript

1case 'DONE_TOGGLE': 2 let index = state.todos.findIndex((todo) => todo.id === action.id) 3 state.todos[index].done = !state.todos[index].done 4 return { 5 todos: [...state.todos] 6 }

修正後:

javascript

1case 'DONE_TOGGLE': 2 const index = state.todos.findIndex((todo) => todo.id === action.id) 3 const todo = state.todos[index]; 4 state.todos[index] = { ...todo , done: !todo.done }; 5 return { 6 todos: [...state.todos] 7 } 8

以上、参考になれば幸いです。

投稿2019/06/01 10:56

jun68ykt

総合スコア9058

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

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

tojima

2019/06/01 11:03

ありがとうございます。解決しました! 変更をしたいstateはいつも新しいオブジェクトにする必要があるという認識で大丈夫でしょうか?
jun68ykt

2019/06/01 11:11

はい。その認識で、(ほぼ)間違ってないです。 逆にいうと、新しいオブジェクトにした場合、内容が変わっていなくても (shouldUpdateComponent で制御しない限りは)render されます。 たとえば以下 case 'DONE_TOGGLE':   const index = state.todos.findIndex((todo) => todo.id === action.id)   const todos = state.todos.map(todo => ({...todo}));   todos[index].done = !todos[index].done;   return {    todos   } のようにして、すべての要素を新しいオブジェクトにすると、変更していないほうのTodoSummaryのrender も呼ばれることになります。
tojima

2019/06/01 11:16

大変参考になりました。
jun68ykt

2019/06/01 11:17

どういたしまして。解決されようでよかったです ????
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問