好吧,我会尽力解释我的项目是如何设置的,这样你就可以适当地帮助我找到如何处理这个配置。
我的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
布尔值告知是否显示页脚。以下是<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/>
&amp;作为SVG的<Next/>
组件。我试图做的是为我提取的提示创建一个滑块。显然,<Footer/>
组件将需要相同的功能,但控制除提示之外的其他数据。因为我是React
&amp;的新手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;
感谢您随时阅读/回复/协助此问题。我是一个相当新的开发人员,这也是我的新技术。
答案 0 :(得分:1)
我不确定你是如何实现你的Next和Previous组件的,但是既然你已经使用了React-Redux,你可以创建额外的Containers来包装这些组件并将Redux Action传递给它们,例如: / p>
// 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操作直接连接到组件中,而无需从应用程序的根组件传递它们。此外,执行此操作可以隔离调用某些操作的位置。您的Previous按钮可能是唯一想要调用Previous操作的组件,因此通过将其放在组件周围的Container包装器中,您可以确保Previous操作仅用于需要它的位置。
编辑:
如果您必须处理多个操作,最好在更高级别定义它们。在这种情况下,由于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>
},
});
将操作向下传递到子组件,直到到达Previous组件,然后将操作附加到Previous组件上的“onClick”处理程序。
这背后的想法是,您希望将参数范围限制为尽可能少的代码。例如,如果您在页面上添加了显示用户信息的配置文件组件,则可能需要在该组件周围添加容器,并传递与用户相关的信息/操作,而不将信息传递给应用程序的其余部分。通过这样做,可以更轻松地将信息集中在需要的地方。如果您必须修复错误,它还可以帮助您确定代码中发生的某些更改/操作的位置。
在上面的示例中,如果Dashboard组件是您的根组件,您只需将Redux操作传递到包装它的容器中。但是,如果您的仪表板组件本身是嵌套组件,请通过自定义容器将操作传递给它,以便操作不会传播到不需要查看它的代码:
<AppRoot>
<PageHeader/>
<DashboardContainer />
<PageSidebar />
<PageFooter />
</AppRoot>