2016-12-14 3 views
0

申し訳ありませんが、この設定に近づける方法を理解するためにプロジェクトをセットアップする方法を説明するために最善を尽くします。2つのReactの子コンポーネントをonClick機能付きで通信する

parent componentは、smart componentです。このコンポーネントを通して、私の店の私のすべてのデータにアクセスしています。

class DashboardPage extends React.Component { 
    componentDidMount() { 
    this.props.getTips(); 
    } 

    render() { 
    return (
     <div> 
     <div className="row"> 
      <div className="col-sm-7"> 
      <ContentBox 
       title="The Scoop" 
       footerText="Submit a Story" 
       showSlider 
       content={<TipOfTheDay tips={this.props.tips} />} 
      /> 
      </div> 
     </div> 
     </div> 
    ) 
    } 
} 

DashboardPage.propTypes = { 
    getTips: PropTypes.func 
} 

function mapStateToProps(state, ownProps) { 
    tips: state.tips 
} 

function mapDispatchToProps(dispatch) { 
    return { 
    getTips:() => { dispatch(tipActions.loadTips());} ## This hits tipActions and runs the `action creator`: loadTips(). Which returns all tips from api. 
    } 
} 

export default connect(mapStateToProps, mapDispatchToProps)(DashboardPage); 

あなたが見ることができるように、私は私のsmart component内側に2 dumb components<ContentBox/> & <TipOfTheDay/>が含まれています。 dashboardPageには、約のコンポーネントがあり、それぞれヘッダ/フッタの特別なタイトルを継承し、フッタをshowSliderブール値で表示するかどうかを指定します。ここで<ContentBox/>は、次のようになります。

import React, {PropTypes} from 'react'; 
import Footer from './ContentBoxFooter'; 

const ContentBox = ({title, footerText, showSlider, content}) => { 
    return (
    <div style={styles.root} className="col-sm-12"> 
     <div style={styles.header} className="row"> 
     <h3 style={styles.header.title}>{title}</h3> 
     <span style={styles.header.arrow} /> 
     </div> 
     {content} 
     <Footer footerText={footerText} showSlider={showSlider} /> 
    </div> 
); 
}; 

ContentBox.propTypes = { 
    title: PropTypes.string, 
    footerText: PropTypes.string, 
    showSlider: PropTypes.bool, 
    content: PropTypes.object 
}; 

export default ContentBox; 

そしてここにフッターです:

import React, {PropTypes} from 'react'; 
import styles from './contentBoxStyles'; 
import Previous from './svg/Previous'; 
import Next from './svg/Next'; 
import Add from './svg/Add'; 
import consts from '../../styles/consts'; 

const ContentBoxFooter = ({footerText, showSlider}) => { 
    if (footerText != undefined) { 
    return (
     <div style={styles.footer} className="row"> 
     { 
      showSlider ? 
      <div> 
       <Previous fillColor={consts.orange} height="20px" width="20px"/> 
       <span style={styles.bar}>|</span> 
       <Next fillColor={consts.orange} width="20px" height="20px"/> 
      </div> : <div style={styles.emptyArrow} /> 
     } 
     <div style={styles.footer.link}> 
      <span style={styles.footer.link.text}>{footerText}</span> 
      <Add fillColor={consts.orange} height="24px" width="24px" /> 
     </div> 
     </div> 
    ); 
    } else { 
    return(null); 
    } 
}; 

ContentBoxFooter.propTypes = { 
    footerText: PropTypes.string, 
    showSlider: PropTypes.bool 
}; 

export default ContentBoxFooter; 

少数!ここでは、onClick機能を追加する必要があります。この機能は、SVGである<Previous/> & <Next/>コンポーネントに追加する必要があります。私がしようとしていることは、取り込んだヒント用のスライダーを作成することです。同じ機能を必要としますが、ヒント以外の異なるデータを制御するコンポーネントは、明らかに<Footer/>になります。私がReact & Reduxに新しくなったので、私はこれをどのように実行できるのかよく分かりませんが、 'Redux`のやり方でやります。

はどのようdumb componentsある他のdumb components内にネストされているこれら2つのsvgのコンポーネントは、ページ上の特定のデータをonClickの機能を実行するのですか?私はこれが理にかなったことを望む。より明確にするために、ここで私は<TipOfTheDay/>コンポーネントでやっているものです:

const tipOfTheDay = ({tips}) => { 
    return (
    <div style={styles.tipBody} className="row"> 
     { 
     tips.map(function(tip, key) { 
      return (
      <div key={key} className="myTips"> 
       <h3 style={styles.tipBody.header}>{tip.title}</h3> 
       <p style={styles.tipBody.content}>{tip.content}</p> 
      </div> 
     ); 
     }) 
     } 
    </div> 
); 
}; 

tipOfTheDay.propTypes = { 
    tips: PropTypes.array.isRequired 
}; 

export default tipOfTheDay; 

はあなたが読んで過ごすいつでもいただきありがとうございます/この質問を支援/応答しました。私はかなり新しい開発者であり、これも私にとって新しい技術です。

答えて

1

React-Reduxを使用しているため、どのコンポーネントを実装しているのか分かりません。これらのコンポーネントをラップし、Reduxアクションを渡すために余分なコンテナを作成することができます。あなたのコンポーネントの周囲に直接コンテナラッパーを追加することにより

// PreviousComponent.jsx 
var Previous React.createClass({ 
    propTypes: { 
     goToPrevious: React.PropTypes.func, 
    }, 

    render: function() { 
     return (
      <div onClick={this.props.goToPrevious}> 
       ... 
      </div> 
     ); 
    } 
}; 

export default Previous; 

//PreviousContainer.jsx 
import ReactRedux from 'react-redux'; 
import Previous from './PreviousComponent'; 

var mapStateToProps = (state, props) => { 
    return {}; 
}; 

var mapDispatchToProps = (dispatch) => { 
    return { 
     goToPrevious:() => { 
      dispatch(Actions.goToPrevious()); 
     }, 
    } 
}; 

var PreviousContainer = ReactRedux.connect(
    mapStateToProps, 
    mapDispatchToProps 
)(Previous); 


export default PreviousContainer; 

、あなたは前の画像/スライドへ/何でも直接あなたのリアクトコンポーネントに行くためのReduxのアクションを接続することができます。その後、あなたはContentBoxFooterでアクションを使用したい場合、あなたはPreviousContainerをインポートして、前のコンポーネント、例えばしたい場所に置き:

//ContentBoxFooter.jsx 

import PreviousContainer from './PreviousContainer' 

const ContentBoxFooter = ({footerText, showSlider}) => { 
    if (footerText != undefined) { 
    return (
     <div style={styles.footer} className="row"> 
     { 
      showSlider ? 
      <div> 
       /* 
       * Add the PreviousContainer here where before you were only using your regular Previous component. 
       */ 
       <PreviousContainer fillColor={consts.orange} height="20px" width="20px"/> 
       <span style={styles.bar}>|</span> 
       <Next fillColor={consts.orange} width="20px" height="20px"/> 
      </div> : <div style={styles.emptyArrow} /> 
     } 
     <div style={styles.footer.link}> 
      <span style={styles.footer.link.text}>{footerText}</span> 
      <Add fillColor={consts.orange} height="24px" width="24px" /> 
     </div> 
     </div> 
    ); 
    } else { 
    return(null); 
    } 
}; 

ContentBoxFooter.propTypes = { 
    footerText: PropTypes.string, 
    showSlider: PropTypes.bool 
}; 

をにアクションを渡す容器に次と前のコンポーネントの両方をラップすることによりReduxアクションをアプリケーションのルートコンポーネントから渡すことなくコンポーネントに直接接続することができます。また、これにより、特定のアクションが呼び出される場所を特定することができます。前のボタンはおそらくPreviousアクションを呼び出す唯一のコンポーネントなので、コンポーネントの周りのContainerラッパーに配置することで、Previousアクションが必要な場所でのみ使用されていることを確認しています。

編集:

あなたが複数のアクションに対処する必要がある場合、それはより高いレベルでそれらを定義することをお勧めします。あなたまでの子コンポーネントを下のアクションを渡し

var DashboardApp = React.createClass({ 
    propTypes: { 
     TipsPrevious: React.PropTypes.function, 
     NewsPrevious: React.PropTypes.function, 
    }, 

    render: function() { 
     <div> 
      <ContentBox 
       previousAction={this.props.TipsPrevious} 
       contentType='Tips' 
      /> 
      <ContentBox 
       previousAction={this.props.NewsPrevious} 
       contentType='News' 
      /> 
      ... 
     </div> 
    }, 
}); 

:ContentBoxが共通の破断点があるので、この場合、私は、コンテンツボックスの種類ごとに別々の前のアクションを定義し、各ContentBoxインスタンスにそれらを渡します前のコンポーネントに到達し、そのアクションを前のコンポーネントの 'onClick'ハンドラにアタッチします。

ここでの考え方は、パラメータの範囲を可能な限り少ないコードに制限したいということです。たとえば、ページにユーザー情報を示すプロファイルコンポーネントを追加した場合、そのコンポーネントの周りにコンテナを追加して、アプリケーションの残りの部分に情報を渡すことなく、ユーザー関連の情報/アクションを渡すことができます。これにより、必要な場所に情報を集中させることが容易になります。また、バグを修正する必要がある場合に、コード内で何らかの変更/アクションがどこで発生しているのかを把握するのに役立ちます。

上記の例では、Dashboardコンポーネントがルートコンポーネントである場合は、Reduxアクションをラップするコンテナに渡します。ただし、ダッシュボードコンポーネントがネストされたコンポーネントそのものである場合は、アクションをカスタムコンテナを介してそのコンポーネントに渡して、アクションをコードを必要としないコードに広げないようにします。

<AppRoot> 
    <PageHeader/> 
    <DashboardContainer /> 
    <PageSidebar /> 
    <PageFooter /> 
</AppRoot> 
+0

ご意見ありがとう!私はあなたのアプローチを理解していると思いますが、1つの質問があります。私はこのフッタに複数の ''コンポーネントを使用しています。想像すると、3つのフッタはすべてこの 'スライダ'機能を持っています。これらの生成されたコンポーネントのそれぞれが異なるデータに対して個別に機能する必要がある場合、このソリューションは機能しますか?例:1つのスライダは 'ヒント'コンポーネントに影響を与えます。 – Nappstir

+0

あなたのコメントに答えて私の答えを更新しました。 – Copernicus

関連する問題