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

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

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

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

React.js

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

Q&A

解決済

1回答

2149閲覧

React:stateの値がループすると変わってしまう(DOMに反映されない)

uchida_yuma

総合スコア44

Redux

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

React.js

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

0グッド

4クリップ

投稿2020/01/17 10:10

前提・実現したいこと

React-Reduxで多言語対応Webアプリを作っています。

APIからJSONを取得して、JSONの中身を翻訳し、翻訳済みの文字列をstateセットし、DOMに反映することです。

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

JSONの中身を翻訳し、stateにセットできている事までは確認できていますが、なぜか map でループすると中身が翻訳前になってしまいます。

Redux-sagaを利用しており、流れは

componentDidMount()でAPIを叩く(/components/home.js)
→ APIから返ってきたJSONをgoogle translateで翻訳 (/sagas/index.js)
→ reducerを通して、stateにセット(/reducers/indexReducer.js)
→ mapループで要素を作成(/components/home.js)
→ DOMに反映(/components/home.js)
の流れになっています。

consoleで確認すると日本語ですが、DOMは英語になってしまいます。
イメージ説明

該当のソースコード

/components/home.js

javascript

1import React, { Component } from 'react'; 2import HeaderComponent from './layouts/Header'; 3import FooterComponent from './layouts/Footer' 4 5// CSS 6import '../css/layout.scss'; 7 8class Home extends Component { 9 constructor(props) { 10 super(props) 11 this.state = {} 12 } 13 componentDidMount = async () => { 14 await console.log('did mount'); 15 16 await this.props.getTrips(this.props.lng) 17 await console.log(this.props.trips); 18 19 } 20 21 render() { 22 console.log('Homelng' + this.props.lng); 23 // ここでconsole.logすると翻訳済みの本文が確認できる 24console.log(this.props.trips); 25 26 let i = 0 27 // ここでループすると中身が英語に戻ってしまう 28 const contents = this.props.trips.map(val => 29 <li className='index-ul__item' key={i++}> 30 <img src={val.picture_urls[0]} className='index-ul__image' /> 31 <h3>{val.title}</h3> 32 <p className='index-ul-icons'> 33 {val.description} 34 </p> 35 </li > 36 ) 37 38 console.log(contents); 39 40 return ( 41 <> 42 <HeaderComponent props={this.props} /> 43 <ul>{contents}</ul> 44 <FooterComponent /> 45 </> 46 ) 47 } 48} 49 50export default Home;

/sagas/index.js

javascript

1// import Axios from "axios" 2import { call, put, takeLatest, takeEvery } from 'redux-saga/effects' 3import * as Api from '../helpers/api' 4import * as F2 from '../helpers/functions' 5 6function* getTrips(action) { 7 8 let tempTrips = yield call(Api.fetch) 9 10 const trips = F2.tripTranslate(tempTrips, action.payload.lng) 11 // ここでconsole.logすると翻訳済みの本文が確認できる 12 13 yield put({ type: "GET_TRIPS_SUCCESS", trips: trips }) 14} 15 16// INDEX Action が送出されるたびにfunctionを起動 17function* rootSaga() { 18 yield takeEvery("GET_TRIPS", getTrips) 19 //アクションタイプgettypeが実行された時はredux-sagaで検知して、経由 20} 21 22export default rootSaga;

/reducers/indexReducer.js

javascript

1const initialState = { 2 trips: [], 3 lng: 'jp', 4 source: '', 5} 6// Reducer処理 7export const indexReducer = (state = initialState, action) => { 8 switch (action.type) { 9 case 'GET_TRIPS_SUCCESS': { 10 return Object.assign({}, state, { 'trips': action.trips }) 11 } 12 case 'LANG_CHANGE': { 13 return Object.assign({}, state, action.payload) 14 } 15 case 'MARKDOWN': { 16 return Object.assign({}, state, action.payload) 17 } 18 default: { 19 return state 20 } 21 } 22}

/helpers/functions.js

javascript

1// google翻訳は jpではなく、 jaで指定する必要があるので注意!! 2// use a callback function to setState 3export function tripTranslate(array, lng) { 4 if (lng === 'jp') { lng = 'ja' } 5 console.log('functionsの言語:' + lng); 6 7 array.forEach((element, i) => { 8 googleTranslate.translate(element.title, lng, function (err, translation) { 9 array[i].title = translation.translatedText 10 }); 11 googleTranslate.translate(element.description, lng, function (err, translation) { 12 array[i].description = translation.translatedText 13 }); 14 googleTranslate.translate(element.notes, lng, function (err, translation) { 15 array[i].notes = translation.notes 16 }); 17 }); 18 return array 19}

試したこと

問題の切り分けとして、別のstateを更新(GIFは言語設定のstateを jp → enに変更したらなぜか日本語になります)
*クリックしているボタンは言語設定のstateを更新するボタンです。

イメージ説明

これくらいしかヒントがなく申し訳ありません。

何らかのstate更新タイミングの問題のような気がしていますが、はっきりしないので、何かお気づきの点があれば教えていただけると助かります。よろしくお願いいたします。

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

node.js : 12.0.4
react: 16.8
redux : 7.1.3
"google-translate": "^3.0.0",

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

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

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

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

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

FKM

2020/01/27 01:10 編集

react のメソッドでreturnを使って値を返してしまうと同期処理が切れてしまった気がします
退会済みユーザー

退会済みユーザー

2020/01/29 06:13

提示されているファイルが一個足りてないことはないでしょうか Home.jsとは別にredux-sagaのactionとreduxsのstateをHome.jsにマッピングしているファイルがあると思うのですが、そこの内容を見てみたら原因がわかるかもしれません
uchida_yuma

2020/02/13 07:12

みなさまご回答ありがとうございました。 自己解決しました。結論は Redux sagaの yieldで使うメソッドの1つがpromiseを返していなかったため、同期処理が切れているためでした。
guest

回答1

0

ベストアンサー

Chromeでデバッグしてるのであれば
redux-loggerを使うことをお勧めします。
こちらでactionがdispatchされた後に入ってるstateのデータが変更されているかどうかが分かります。

されていれば、レンダリングまたはconnectでpropsにマッピングした時に問題が起きている。
されていなければdispatchしたペイロードあるいはreducerのactionTypeの不一致などの問題などが起きている可能性があります。

怪しいのは

typescript

1 googleTranslate.translate(element.title, lng, function (err, translation) { 2 array[i].title = translation.translatedText 3 }); 4 googleTranslate.translate(element.description, lng, function (err, translation) { 5 array[i].description = translation.translatedText 6 }); 7 googleTranslate.translate(element.notes, lng, function (err, translation) { 8 array[i].notes = translation.notes 9 });

この辺が同期メソッドであるかを確認してみてください。
this.props.tripsのマッピングについてもうまくいっていない可能性があります。

const contents = this.props.trips.map(val => <li className='index-ul__item' key={i++}> <img src={val.picture_urls[0]} className='index-ul__image' /> <h3>{val.title}</h3> <p className='index-ul-icons'> {val.description} </p> </li > )

また、この文ですが、外部のコンポーネントに要素を切り出すことをお勧めします。
毎回変数でコンポーネントを内部で作成して保管するのはパフォーマンス的にもよくありませんし、レンダリングが毎回走るためバグの温床になりやすくなります。

投稿2020/01/29 06:22

編集2020/01/29 06:22
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問