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の使い方に問題があるのでしょうか。
微妙な質問を繰り返してしまい申し訳ありません。
良かったら教えて頂けると助かります。
よろしくお願いします。
回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。