React:将简单的逻辑放在 Container 或 Presentational 组件中?
React: To put simple logic in Container or Presentational component?
我有一个容器组件,它将对象数组向下传递到表示组件以进行输出。
在演示组件中,我需要显示满足特定条件的这些对象的数量。最好的做法是在容器组件中执行计数并将其传递给展示组件,还是在展示组件中执行此计数。
即:
export class ResultsPage extends React.Component {
constructor(props){
super(props);
}
countSexyObjects(){
const matching = this.props.allObjects.filter((obj)=>{
return obj.sexy === true;
});
return matching.length
}
render(){
return (
<PresentationalComponent allObjects={this.props.allObjects}
numberOfSexyObjects={this.countSexyObjects()} />
);
}
}
let PresentationalComponent = (props) => {
return (
<div>
There are {props.numberOfSexyObjects} sexy objects
</div>
);
};
或
export class ResultsPage extends React.Component {
constructor(props){
super(props);
}
render(){
return (
<PresentationalComponent allObjects={this.props.allObjects} />
);
}
}
let PresentationalComponent = (props) => {
const countSexyObjects = () => {
const matching = this.props.allObjects.filter((obj)=>{
return obj.sexy === true;
});
return matching.length
};
return (
<div>
There are {countSexyObjects()} sexy objects
</div>
);
};
出于以下几个原因,我会使用第一种格式:
智能组件应该更好地理解 "SexyObject" 是什么。如果它是对象中的一个字段,那很简单,可以用任何一种方式争论。如果它依赖于 Web 服务或一些更复杂的逻辑来确定它是否性感,那么您永远不会希望在表示层中使用它。简单有一种变复杂的方式,所以我最初会使用支持复杂性的结构。
使用智能组件中的逻辑测试代码会更简单。您可以启动组件,然后检查固定数据集中的输出变量。
如果 "SexyObject" 的标准可以由组件更改,如果您将选择逻辑分开,您将保留重用您的展示组件的能力。
只要我的 0.02 美元
理想状态在 React 中被认为是一种邪恶。我知道 React 是建立在状态的概念之上的,但是状态越少越好,这意味着尝试使用本质上纯的函数来构建代码。
恕我直言,您的第一个示例更正确。 ResultsPage
是您的容器组件(智能组件),而另一个是愚蠢的。 Dumb 组件不管理状态,只负责 UI 的外观。您可以将所有 html、bootstrap 逻辑放在那里。
这个模式之所以好,是因为现在假设你想从 XHR 调用中获取匹配条件,在第二种情况下你的代码将是
export class ResultsPage extends React.Component {
constructor(props){
super(props);
}
getSexyMatcher() {
/* make ajax call here */
return results;
}
render(){
return (
<PresentationalComponent allObjects={this.props.allObjects} sexyMatcher={getSexyMatcher()}/>
);
}
}
let PresentationalComponent = (props) => {
const countSexyObjects = () => {
const matching = this.props.allObjects.filter((obj)=>{
return obj.sexy.match(props.sexyMatcher)
// return obj.sexy === true;
});
return matching.length
};
return (
<div>
There are {countSexyObjects()} sexy objects
</div>
);
};
注意到您是如何为相同的业务逻辑更改两个组件的吗?更糟糕的是,如果其他人在代码库的其他地方使用了 PresentationalComponent
怎么办?
在第一种情况下,事情要简单得多。只需在智能组件中添加 ajax 函数并将结果传递给 UI 组件即可。
我有一个容器组件,它将对象数组向下传递到表示组件以进行输出。
在演示组件中,我需要显示满足特定条件的这些对象的数量。最好的做法是在容器组件中执行计数并将其传递给展示组件,还是在展示组件中执行此计数。
即:
export class ResultsPage extends React.Component {
constructor(props){
super(props);
}
countSexyObjects(){
const matching = this.props.allObjects.filter((obj)=>{
return obj.sexy === true;
});
return matching.length
}
render(){
return (
<PresentationalComponent allObjects={this.props.allObjects}
numberOfSexyObjects={this.countSexyObjects()} />
);
}
}
let PresentationalComponent = (props) => {
return (
<div>
There are {props.numberOfSexyObjects} sexy objects
</div>
);
};
或
export class ResultsPage extends React.Component {
constructor(props){
super(props);
}
render(){
return (
<PresentationalComponent allObjects={this.props.allObjects} />
);
}
}
let PresentationalComponent = (props) => {
const countSexyObjects = () => {
const matching = this.props.allObjects.filter((obj)=>{
return obj.sexy === true;
});
return matching.length
};
return (
<div>
There are {countSexyObjects()} sexy objects
</div>
);
};
出于以下几个原因,我会使用第一种格式:
智能组件应该更好地理解 "SexyObject" 是什么。如果它是对象中的一个字段,那很简单,可以用任何一种方式争论。如果它依赖于 Web 服务或一些更复杂的逻辑来确定它是否性感,那么您永远不会希望在表示层中使用它。简单有一种变复杂的方式,所以我最初会使用支持复杂性的结构。
使用智能组件中的逻辑测试代码会更简单。您可以启动组件,然后检查固定数据集中的输出变量。
如果 "SexyObject" 的标准可以由组件更改,如果您将选择逻辑分开,您将保留重用您的展示组件的能力。
只要我的 0.02 美元
理想状态在 React 中被认为是一种邪恶。我知道 React 是建立在状态的概念之上的,但是状态越少越好,这意味着尝试使用本质上纯的函数来构建代码。
恕我直言,您的第一个示例更正确。 ResultsPage
是您的容器组件(智能组件),而另一个是愚蠢的。 Dumb 组件不管理状态,只负责 UI 的外观。您可以将所有 html、bootstrap 逻辑放在那里。
这个模式之所以好,是因为现在假设你想从 XHR 调用中获取匹配条件,在第二种情况下你的代码将是
export class ResultsPage extends React.Component {
constructor(props){
super(props);
}
getSexyMatcher() {
/* make ajax call here */
return results;
}
render(){
return (
<PresentationalComponent allObjects={this.props.allObjects} sexyMatcher={getSexyMatcher()}/>
);
}
}
let PresentationalComponent = (props) => {
const countSexyObjects = () => {
const matching = this.props.allObjects.filter((obj)=>{
return obj.sexy.match(props.sexyMatcher)
// return obj.sexy === true;
});
return matching.length
};
return (
<div>
There are {countSexyObjects()} sexy objects
</div>
);
};
注意到您是如何为相同的业务逻辑更改两个组件的吗?更糟糕的是,如果其他人在代码库的其他地方使用了 PresentationalComponent
怎么办?
在第一种情况下,事情要简单得多。只需在智能组件中添加 ajax 函数并将结果传递给 UI 组件即可。