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

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

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

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

Onsen UI

HTML5で記述されたモバイルアプリの高速化、およびネイティブアプリライクなUIが作れるフレームワーク。 様々なJavaScriptフレームワークと併せて使用することができます。スマートフォン向けアプリ、Webサイトに必要なアニメーション、UI/UXを実装することが可能になります。

React.js

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

Q&A

解決済

3回答

2888閲覧

親コンポーネントから子コンポーネントにpropsを伝達できない

退会済みユーザー

退会済みユーザー

総合スコア0

Redux

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

Onsen UI

HTML5で記述されたモバイルアプリの高速化、およびネイティブアプリライクなUIが作れるフレームワーク。 様々なJavaScriptフレームワークと併せて使用することができます。スマートフォン向けアプリ、Webサイトに必要なアニメーション、UI/UXを実装することが可能になります。

React.js

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

0グッド

0クリップ

投稿2017/09/26 02:32

編集2017/10/01 08:36

React,Redux初心者です。
monaca,React,Redux,OnsenUIを使ってアプリケーションを作成しています。

今回、OnsenUIのNavigatorを使っているのですが、上手くpropsを伝達できません。どこに問題があるのでしょうか。

javascript

1class AlertMainPage extends React.Component{ 2 3 componentWillMount(){ 4 const that = this 5 const AlertDB = ncmb.DataStore("Alert") 6 AlertDB.fetchAll() 7 .then(function(results){ 8 that.props.showAlertPage(results.length) 9 }) 10 .catch(function(err){ 11 console.log(err) 12 }) 13 } 14 15 render(){ 16 const AlertContent = styled.div` 17 height: 100%; 18 ` 19 const props = this.props 20 const alertViewList = [] 21 for(var i=this.props.idLen-1; i>=0; i--){ 22 alertViewList.push(<AlertView {...props} id={i}/>) 23 } 24 25 26 console.log('-----------------'); 27 console.log(this.props); 28 console.log(this.props.idLen); 29 console.log(props.idLen); 30 31 32 return( 33 <Page 34 renderToolbar={() => 35 <Toolbar modifier="material"> 36 <div className='center'>Alert</div> 37 </Toolbar> 38 }> 39 <AlertContent> 40 {alertViewList} 41 </AlertContent> 42 </Page> 43 ) 44 } 45} 46 47//AlertはContainerConponentです。 48class Alert extends React.Component{ 49 renderPage(route,navigator) { 50 const props = route.props || {}; 51 props.navigator = navigator; 52 return React.createElement(route.component, props) 53 } 54 55 render() { 56 const props = this.props 57 console.log(`Alert ${this.props.idLen}`) 58 return ( 59 <Navigator 60 swipeable 61 initialRoute={{ 62 component: AlertMainPage, 63       //この辺が全然わからない 64 props: {...props}, 65 idLen: this.props.idLen, 66 }} 67 renderPage={this.renderPage} 68 /> 69 ); 70 } 71}

【追記】
若干進みました。
質問時は本当にどこに問題があるのかわからない状態でした。
・Reduxの設計に問題がある
・OnsenUIの使い方に問題がある

ですが色々試してみて前者については問題ないことがわかりました。

先程のコードをOnsenUIのNavigatorを使わずに似たような構造にしてみました。

javascript

1class TestNavi extends React.Component { 2 render() { 3 return( 4 <AlertMainPage {...this.props}/> 5 6 ) 7 } 8} 9 10class Alert extends React.Component{ 11 12 render() { 13 console.log(`Alert ${this.props.idLen}`) 14 return ( 15 <TestNavi {...this.props}/> 16 ); 17 } 18}

するとconsoleには理想通りの値が出力されました。

ですので、今僕がわからないのは、
**「OnsenUIのNavigatorを使う時にどのようにしたら親コンポーネントから子コンポーネントにpropsを伝達できるか。」**です。

一般的には親コンポーネントから子コンポーネントにpropsを伝達していくときはバケツリレーを避けるためにSpread Attributesを利用するかと思いますが、なぜか上手く行きません。

javascript

1class Alert extends React.Component{ 2 renderPage(route,navigator) { 3 const props = route.props || {}; 4 props.navigator = navigator; 5 return React.createElement(route.component, props) 6 } 7 8 render() { 9 console.log(`Alert ${this.props.idLen}`) 10 return ( 11 <Navigator 12 {...this.props} //普通はココ? 13 swipeable 14 initialRoute={{ 15 component: AlertMainPage, 16 props: {...this.props}, //今回のみココ?でもうまくいかない..。(「普通はココ?」のときよりは若干マシな結果になる) 17 }} 18 renderPage={this.renderPage} 19 /> 20 ); 21 } 22}

またreact-onsenuiのNavigatorのrender()内を見ても、Spread Attributesを使っているように見えますが、なかなか理想通りに動きません。

javascript

1 render() { 2 const {...others} = this.props; 3 Util.convert(others, 'animationOptions', {fun: Util.animationOptionsConverter, newName: 'animation-options'}); 4 const pages = this.routes ? this.routes.map((route) => this.props.renderPage(route, this)) : null; 5 6 return ( 7 <ons-navigator {...others} ref='navi'> 8 {pages} 9 </ons-navigator> 10 ); 11 } 12}

上のリンクの公式ドキュメントを読んだり、実際にNavigatorコンポーネントの中身を読んだりしてみたのですが、いまいち理解することが出ませんでした。

どなたかわかる方がいらっしゃれば教えていただけませんでしょうか。
よろしくお願いします。

【捕捉】
Action

javascript

1import * as actionTypes from '../actionTypes' 2 3//Alert 4export const loadAlertPageAction = (idLen) => { 5 return{ 6 type: actionTypes.ALERT_PAGE_LOAD, 7 idLen, 8 } 9}

Reducer

javascript

1import * as actionTypes from '../actionTypes' 2 3const initialState = { 4 idLen: null, 5} 6 7//Alert 8export const alertReducer = (state = initialState, action) => { 9 10 switch(action.type){ 11 case actionTypes.ALERT_PAGE_LOAD: 12 return Object.assign({}, state, { 13 idLen: action.idLen, 14 }) 15 default: 16 return state 17 } 18 19}

【追記の追記】
質問時の私の理解不足のせいで、もはや若干違う質問になってしまっているかもしれませんが、まだ解決していないのでここで追記して質問を続けさせていただきます。

jaavascript

1class AlertNavi extends React.Component{ 2 //ここから 3 constructor(props){ 4 super(props) 5 this.state = { 6 idLen: this.props.idLen, 7 }; 8 } 9 //ここまではあってもなくても何も変わらない。 10 11 componentWillMount(){ 12 const that = this 13 const AlertDB = ncmb.DataStore("Alert") 14 AlertDB.fetchAll() 15 .then(function(results){ 16 that.props.showAlertPage(results.length) 17 }) 18 .catch(function(err){ 19 console.log(err) 20 }) 21 } 22 23 render(){ 24 const AlertContent = styled.div' 25 height: 100%; 26 ' 27 console.log("this.props.idLen=" + this.props.idLen); 28 29 const alertList = [] 30 let idLen = this.props.idLen 31 for(var i=idLen-1; i>=0; i--){ 32 alertList.push(<RenderAlert {...this.props} id={i}/>) 33 } 34 35 return( 36 <Page 37 renderToolbar={() => 38 <Toolbar modifier="material"> 39 <div className='center'>アラート</div> 40 </Toolbar> 41 }> 42 <AlertContent> 43 {alertList} 44 </AlertContent> 45 </Page> 46 ) 47 } 48} 49 50class Alert extends React.Component{ 51 52 renderPage(route, navigator) { 53 const props = route.props || {}; 54 props.navigator = navigator; 55 56 return React.createElement(route.component, props); 57 } 58 59 render() { 60 console.log("idLen=" + this.props.idLen); 61 return ( 62 <Navigator 63 initialRoute={{ 64 component: AlertNavi, 65 props:{ 66 idLen: this.props.idLen, 67 showAlertPage: this.props.showAlertPage, 68 }, 69 // props:{...this.props}, 70 }} 71 renderPage={this.renderPage} 72 /> 73 ); 74 } 75} 76

実際に実行した時のコンソールの表示が以下の画像です。
コンソールの表示

1回目(?)にreduxのactionが実行されて(画像1行目、2行目)、idLenの値が変更され、nullから2に変わっています。(親コンポーネントの中では)(画像3行目)
しかし問題なのはその次で、その変更されたidLenが子コンポーネントに伝わっていません(画像4行目)

なのでpropsの伝達はできているのはできていると思うのですが、やはりまだ完璧には上手く行っていません。
これは恐らくはOnsenUIの使い方に問題があるのではなく、Reactの設計(ライフサイクルなど実行のタイミングなど)に問題があるのでしょうか。
しかし、追記でも書いたようにOnsenUIのNavigatorを使わずに同じような流れにしてみると、実際うまく行っているので、やはりこのNavigatorの使い方に問題があるのでしょうか。

微妙な質問を繰り返してしまい申し訳ありません。
良かったら教えて頂けると助かります。
よろしくお願いします。

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

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

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

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

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

guest

回答3

0

ベストアンサー

propsの伝達ができないのはコンポーネントの組み合わせ方に問題がありました。

結論を書くと

main → Tabbar ─→ Navigator → A → B → C └→ Navigator → A' → B' → C'

という構成です。
AコンポーネントはReduxのProviderなどを使うところ
BはContainerComponent
CはPresentationalConponentです。

TabbarとNavigatorをこの親子関係で組み合わせることで、Reduxも上手く動作するようになりました。

単純にNavigatorを使ってpropsを渡したい場合は

<Navigator // {...this.props} ここではない! initialRoute={{ component: PageAlert, props: {...this.props}, // ここ! }} renderPage={this.renderPage} />

こんな感じで書くと良さそうです。

また、さらに詳しくまとめましたので良かったら読んでみて下さい
OnsenUI(React)のNavigator,Tabbar+Reduxを使う時の構成の注意点について

投稿2017/10/03 03:01

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

参考にならないかもしれませんが、
私の場合は、以下のやり方で、コンポーネント間でpropsを伝達しています。
例)コンポーネントA→コンポーネントBへNavigatorでPushPageでの画面遷移した時のpropsの値の引き渡し。

 コンポーネントA
this.props.navigator.pushPage({
component: コンポーネントB,
props: {
value: 'hoge',// 設定値
},
});

コンポーネントB
/* コンストラクタ */
constructor(props) {
super(props);// これは必要

this.state = { data: this.props.value,// コンポーネントAのpropsのvalueを取得 };

受け手側のコンポーネントBのコンストラクタで、super(props);を行った後、
コンポーネントAで設定したpropsのvalueの値を引き渡すことが出来ます。

投稿2017/09/29 06:40

toshi_7710

総合スコア23

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

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

退会済みユーザー

退会済みユーザー

2017/09/29 07:50

回答ありがとうございます もう少し詳しくお聞きしたいのですが、コンポーネントAというのは <Navigator />と書いてあるコンポーネントのことでしょうか。 だとしたら、NavigatorのinitialRouteなどは何と書いてあるのでしょうか。
toshi_7710

2017/09/29 09:17

すみません、親コンポーネントではなく、子コンポーネントでした。 子コンポーネント間のpropsの連携でした。 コンポーネントAは、以下の定義になります。 export default class コンポーネントA extends React.Component {  中身は省略 }
toshi_7710

2017/09/29 09:21

<Navigator/>と書かれた親コンポーネントから子コンポーネント間の同じやり方で、propsの値は連携できます。 親コンポーネント render() { return ( <Navigator initialRoute={{ component: 子コンポーネント ,props:{ idLen: 3 } }} renderPage={this.renderPage} /> ); } 子コンポーネント export default class 子コンポーネント extends React.Component { constructor(props) { super(props); console.log("this.props.idLen=" + this.props.idLen);//3と出力される。 } }
退会済みユーザー

退会済みユーザー

2017/10/01 07:41

ありがとうございます。 OnsenUIのNavigatorに関してはtoshi_7710さんの意見を参考にするとうまくいきました。ありがとうございます。 しかし、まだ(恐らくはReact設計に関して)、問題が解決していないので、もしよろしければ追記の追記の部分についてアドバイス頂けるとうれしいです。 よろしくお願いします。
guest

0

reducerとactionのコードも記述してもらえますか?

投稿2017/09/26 04:59

y_y3

総合スコア179

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

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

退会済みユーザー

退会済みユーザー

2017/09/26 05:06

回答ありがとうございます。 追記しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問