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

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

詳細はこちら
Redux

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

React.js

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

Q&A

解決済

1回答

4593閲覧

Reduxでstateをreducer経由で変更しても再レンダリングされない

uchida_yuma

総合スコア44

Redux

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

React.js

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

0グッド

0クリップ

投稿2019/09/16 03:39

前提・実現したいこと

いつもお世話になってます。この度ReactにReduxを導入すべき基本的なReduxによるstate更新と再レンダリングまで行いたいと思い、まずは最低限Reduxを導入 → Redux経由でstate変更 → DOMに反映

まで行いたいです。

サンプルとして、↓スクショの「LIKE!」 をクリックすると、その下の文言が変わるコードを書いています。

イメージ説明

発生している問題・エラーメッセージ

Redux経由でstate変更まではできているが、DOMに反映されない

該当のソースコード

Container

1import { connect } from 'react-redux'; 2import * as actions from '../actions/Index'; 3import Index from '../components/Index'; 4 5const mapStateToProps = state => { 6 return { 7 user: state.user, 8 emojies: state.emojies, 9 liked: state.liked, 10 } 11} 12 13const mapDispatchToProps = dispatch => { 14 return { 15 getEmojies: () => dispatch(actions.getEmojies()), 16 addLike: () => dispatch(actions.addLike()), 17 } 18} 19 20export default connect(mapStateToProps, mapDispatchToProps)(Index)

component

1import React, { Component, PropTypes } from 'react'; 2 3export default class Index extends Component { 4 constructor(props) { 5 super(props); 6 } 7 8 componentDidMount = (props) => { 9 this.props.getEmojies 10 } 11 12 render() { 13 // StoreのTodoからリストを生成 14 // const list = this.props.emojies.map((emoijes, index) => <li key={index}>{source}</li>) 15 console.log(this.props.state) // ←ここでstate更新できていることは確認できる 16 let liked = this.props.state ? 'LIKED!' : 'NO LIKED > <'; 17 return ( 18 <ul className="panel panel-default"> 19 <p onClick={this.props.addLike}>LIKE!</p> 20 {liked} 21 </ul> 22 ); 23 } 24}

actions

1const GET_USER = 'GET_USER' 2const GET_EMOJIES = 'GET_EMOJIES' 3const ADD_LIKE = 'ADD_LIKE' 4 5export const getEmojies = () => { 6 return { 7 type: GET_EMOJIES, 8 }; 9} 10 11export const addLike = () => { 12 return { 13 type: ADD_LIKE 14 }; 15}

reducenr

1import Api from '../helpers/api' 2 3const initialState = { 4 user: [], 5 emoji: [], 6 liked: false 7} 8 9export const indexReducer = (state = initialState, action) => { 10 switch (action.type) { 11 case 'GET_EMOJIES': 12 // 新しく追加するTODO 13 // stateを複製して追加 14 let emojies = { 0: { 'name': 'name' }, 1: { 'name': 'bbbbbbb' } } 15 const newEmojies = Object.assign({}, state, emojies) 16 17 return newEmojies 18 case 'ADD_LIKE': 19 const newLike = Object.assign({}, state, { liked: true }) 20 console.log(newLike); 21 return newLike 22 default: 23 return state 24 } 25}

createStore

1import { createStore as reduxCreateStore, applyMiddleware, combineReducers } from "redux"; 2import logger from "redux-logger"; 3import { indexReducer } from "./reducers/Index"; 4import createSagaMiddleware from 'redux-saga'; 5 6export default function createStore() { 7 const sagaMiddleware = createSagaMiddleware() 8 const store = reduxCreateStore( 9 combineReducers({ 10 state: indexReducer, 11 }), 12 applyMiddleware( 13 logger, 14 sagaMiddleware 15 ) 16 ) 17 18 return store; 19}

Root

1import React, { Component } from 'react'; 2import ReactDOM from 'react-dom'; 3 4import Index from './containers/Index' 5 6import { Provider } from 'react-redux'; 7import createStore from './createStore'; 8 9const store = createStore(); 10 11export default class Root extends Component { 12 render() { 13 return ( 14 <div className="container"> 15 <Index /> 16 </div> 17 ); 18 } 19} 20 21if (document.getElementById('root')) { 22 ReactDOM.render( 23 <Provider store={store}> 24 <Root /> 25 </Provider>, 26 document.getElementById('root')); 27} 28

といったコードで群でstateの更新をしており、componentでstateの更新を確認できています。

試したこと

Reducerでのshallow equal対策として、returnするオブジェクトは新規に作成しなおす

case 'ADD_LIKE': const newLike = Object.assign({}, state, { liked: true })

↓の質問にあるpropToStateの修正
https://teratail.com/questions/61126

全く原因がわからず困っておりますので、何かお気付きの方はご教授いただけますと幸いです。

よろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

packagejson

1 "devDependencies": { 2 "@babel/plugin-proposal-class-properties": "^7.5.5", 3 "@babel/preset-react": "^7.0.0", 4 "axios": "^0.19.0", 5 "cross-env": "^5.1", 6 "laravel-mix": "^4.0.7", 7 "lodash": "^4.17.13", 8 "react": "^16.2.0", 9 "react-dom": "^16.2.0", 10 "resolve-url-loader": "^2.3.1", 11 "sass": "^1.15.2", 12 "sass-loader": "^7.1.0" 13 }, 14 "dependencies": { 15 "react-redux": "^7.1.1", 16 "redux": "^4.0.4", 17 "redux-logger": "^3.0.6", 18 "redux-saga": "^1.0.5" 19 }

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

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

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

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

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

guest

回答1

0

自己解決

オブジェクトの形を理解を再確認したら上手くいきました。
具体的には

createStore

1 combineReducers({ 2 state: indexReducer, 3 }),

この部分が複数のreducerを合体させる前提だったので、プレフィックス「state」にしていることを認識できていなかったため、

container

1const mapStateToProps = state => { 2 return { 3 user: state.state.user, 4 emojies: state.state.emojies, 5 liked: state.state.liked, 6 } 7} 8

のネストをstate.stateにすることで、

component.js

1render() { 2 // StoreのTodoからリストを生成 3 // const list = this.props.emojies.map((emoijes, index) => <li key={index}>{source}</li>) 4 console.log(this.props.state) 5 let liked = this.props.liked ? 'LIKED!' : 'NO LIKED > <';// ←ここでstate更新できていることは確認できる 6 return ( 7 <ul className="panel panel-default"> 8 <p onClick={this.props.addLike}>LIKE!</p> 9 {liked} 10 </ul> 11 ); 12 }

let likedで解決できました!

投稿2019/09/16 06:53

uchida_yuma

総合スコア44

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問