好吧,我将尽力解释我的项目是如何设置的,以便您可以适本地帮助我找出如何处理此配置。
我有一个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);
如您所见,我添加了两个 dumb components
在我的里面smart component
, <ContentBox/>
& <TipOfTheDay/>
。关于dashboardPage
大约有 7 <ContentBox/>
组件,每个组件都继承页眉/页脚的特殊标题,并通过 showSlider
被告知是否显示页脚 bool 值。这是<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
功能。此功能需要添加到 <Previous/>
& <Next/>
组件是一个 SVG。我试图做的是为我拉入的提示创建一个 slider 。显然会有 <Footer/>
需要相同功能但控制除提示之外的不同数据的组件。因为我是React
的新手& Redux
,我不确定如何执行此操作,而不仅仅是执行此操作,而是以“Redux”方式执行此操作。
我如何获得这两个svg
嵌套在其他 dumb components
中的组件那是dumb components
,对页面上的特定数据执行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;
感谢您花时间阅读/回复/协助解决此问题。我是一个相当新的开发人员,这对我来说也是新技术。
最佳答案
我不确定您是如何实现下一个和上一个组件的,但是由于您使用了 React-Redux,您可以创建额外的容器来包装这些组件并向它们传递 Redux Action,例如:
// 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 操作连接到上一个图像/幻灯片/其他内容,直接将其连接到 React 组件中。然后,当您想要在 ContentBoxFooter 中使用该操作时,您可以导入 PreviousContainer 并将其放置在您想要使用 Previous 组件的位置,例如:
//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
};
通过将 Next 和 Previous 组件包装在将操作传递到其中的容器中,您可以将 Redux 操作直接连接到您的组件中,而无需从应用程序的根组件传递它们。此外,这样做可以让您隔离调用某些操作的位置。您的“上一个”按钮可能是唯一想要调用“上一个”操作的组件,因此通过将其放置在该组件周围的容器包装器中,您可以确保仅在需要的地方使用“上一个”操作。
编辑:
如果您必须处理多个操作,最好在更高的级别上定义它们。在这种情况下,由于 ContentBox 是常见的断点,我将为每种类型的内容框定义单独的 Previous 操作,并将它们传递到每个 ContentBox 实例中:
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>
},
});
将操作向下传递到子组件,直到到达上一个组件,然后将操作附加到上一个组件上的“onClick”处理程序。
这背后的想法是您希望将参数的范围限制为尽可能少的代码。例如,如果您添加了一个在页面上显示用户信息的配置文件组件,您可能需要在该组件周围添加一个容器,并传入与用户相关的信息/操作,而不将该信息传递给应用程序的其余部分。通过这样做,可以更轻松地将信息集中在需要的地方。如果您必须修复错误,它还可以帮助您找出代码中发生某些更改/操作的位置。
在上面的示例中,如果 Dashboard 组件是您的根组件,您只需通过包装它的容器将 Redux Actions 传递到其中即可。但是,如果您的仪表板组件本身是嵌套组件,请通过自定义容器将操作传递到其中,以便操作不会传播到不需要查看它的代码:
<AppRoot>
<PageHeader/>
<DashboardContainer />
<PageSidebar />
<PageFooter />
</AppRoot>
关于javascript - 使用 onClick 功能通信两个 React 子组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41153039/