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

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

ただいまの
回答率

89.06%

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

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 619

uchida_yuma

score 44

前提・実現したいこと

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

まで行いたいです。

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

イメージ説明

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

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

該当のソースコード

import { connect } from 'react-redux';
import * as actions from '../actions/Index';
import Index from '../components/Index';

const mapStateToProps = state => {
  return {
    user: state.user,
    emojies: state.emojies,
    liked: state.liked,
  }
}

const mapDispatchToProps = dispatch => {
  return {
    getEmojies: () => dispatch(actions.getEmojies()),
    addLike: () => dispatch(actions.addLike()),
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Index)
import React, { Component, PropTypes } from 'react';

export default class Index extends Component {
  constructor(props) {
    super(props);
  }

  componentDidMount = (props) => {
    this.props.getEmojies
  }

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

export const getEmojies = () => {
  return {
    type: GET_EMOJIES,
  };
}

export const addLike = () => {
  return {
    type: ADD_LIKE
  };
}
import Api from '../helpers/api'

const initialState = {
  user: [],
  emoji: [],
  liked: false
}

export const indexReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'GET_EMOJIES':
      // 新しく追加するTODO
      // stateを複製して追加
      let emojies = { 0: { 'name': 'name' }, 1: { 'name': 'bbbbbbb' } }
      const newEmojies = Object.assign({}, state, emojies)

      return newEmojies
    case 'ADD_LIKE':
      const newLike = Object.assign({}, state, { liked: true })
      console.log(newLike);
      return newLike
    default:
      return state
  }
}
import { createStore as reduxCreateStore, applyMiddleware, combineReducers } from "redux";
import logger from "redux-logger";
import { indexReducer } from "./reducers/Index";
import createSagaMiddleware from 'redux-saga';

export default function createStore() {
  const sagaMiddleware = createSagaMiddleware()
  const store = reduxCreateStore(
    combineReducers({
      state: indexReducer,
    }),
    applyMiddleware(
      logger,
      sagaMiddleware
    )
  )

  return store;
}
import React, { Component } from 'react';
import ReactDOM from 'react-dom';

import Index from './containers/Index'

import { Provider } from 'react-redux';
import createStore from './createStore';

const store = createStore();

export default class Root extends Component {
  render() {
    return (
      <div className="container">
        <Index />
      </div>
    );
  }
}

if (document.getElementById('root')) {
  ReactDOM.render(
    <Provider store={store}>
      <Root />
    </Provider>,
    document.getElementById('root'));
}

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

試したこと

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

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

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

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

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

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

 "devDependencies": {
        "@babel/plugin-proposal-class-properties": "^7.5.5",
        "@babel/preset-react": "^7.0.0",
        "axios": "^0.19.0",
        "cross-env": "^5.1",
        "laravel-mix": "^4.0.7",
        "lodash": "^4.17.13",
        "react": "^16.2.0",
        "react-dom": "^16.2.0",
        "resolve-url-loader": "^2.3.1",
        "sass": "^1.15.2",
        "sass-loader": "^7.1.0"
    },
    "dependencies": {
        "react-redux": "^7.1.1",
        "redux": "^4.0.4",
        "redux-logger": "^3.0.6",
        "redux-saga": "^1.0.5"
    }
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

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

    combineReducers({
      state: indexReducer,
    }),


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

const mapStateToProps = state => {
  return {
    user: state.state.user,
    emojies: state.state.emojies,
    liked: state.state.liked,
  }
}


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

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


let likedで解決できました!

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 89.06%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る