reactjs


React: To put simple logic in Container or Presentational component?


I have a container component which passes an array of objects down to a presentational component to output.
In the presentational component, I need to display the count of a number of these objects that meet certain criteria. Is it best practice to perform the count in the container component and pass it down to the presentational component or is it OK to do this count in the presentational component.
ie:
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>
);
};
OR
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>
);
};
Ideally state is considered an evil in React. I understand that React is built upon the concept of state but less state is more preferred, which means try to structure the code with mostly functions that are pure in nature.
IMHO in your first example is more correct. The ResultsPage is your Container Component(smart component) while the other is dumb. Dumb component doesn't manage state and just takes care of how the UI looks. You can put all the html, bootstrap logic in there.
The reason why this pattern is good is because lets say now you want to fetch the matching criteria from an XHR call, your code in the second case would be
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>
);
};
Notice how you had to change two components for the same business logic? Much worse, what if someone else used that PresentationalComponent elsewhere in the codebase?
In the first case things are much simpler. Just have to add the ajax function in the smart component and pass down the results to the UI component.
I would use the first format for a few reasons:
The smart component should a better idea of what a "SexyObject" is. If its a field in the object, that's pretty simple and could be argued either way. If it relies on a web service or some more complex logic to determine if it is sexy or not, you would never want that in the presentational layer. Simple has a way of turning complex, so I'd use the structure that supports the complexity initially.
Testing the code will be simpler with the logic in the smart component. You can prime your component and then check the output variables from your fixed data set.
If the criteria for "SexyObject" can change by the component, you would retain the ability to reuse your presentational component if you kept the selection logic separate.
Just my $0.02

Related Links

React select onchange doesn't work
ReactDOM vs Fancy Routing Library
is it possible to have nested reducers in redux?
React Redux Lifecycle Props
ScrollView Breaking When Adding Adjacent Component in React/js
How to assert a React component with multiple <a> tags has an <a> tag with a given href
setting this.state in react leaf component when using redux, anti-pattern? benefits / disadvantages
ReactJs img src local image
How can I import the *.xcodeproj of React Native framework into my native project elegantly?
How to handle server push messages and their side effects in React / Redux
redirect from component level after specific dispatch - redux thunk
Detecting a refresh event in react
Get current location from react-router-redux
Video js marker length
How to open Drawer When use a custom icon in Scene
React routing between static and dynamic pages

Categories

HOME
spring-boot
msbuild
locale
windows-server-2008
mifare
watson-iot
arguments
squeak
bitbucket
aggregation-framework
aggregate-functions
hibernate-mapping
webpack-dev-server
annyang
olap
select2
aspectj
decoding
react-select
bookmarklet
brightway
k-means
reportlab
virtuemart
conditional-formatting
sasl
rollupjs
multiple-inheritance
hierarchical-data
launchd
git-submodules
cqlsh
spring-data-gemfire
recreate
openoffice-impress
selenium3
akamai
wordpress-rest-api
kubectl
oracle-nosql
javax
gstreamer-1.0
strategy-pattern
word-wrap
lex
nscollectionview
byobu
cowboy
server-side-swift
java-5
taiga
grails-2.0
mef
nao-robot
evaluation
iban
scikit-image
class-design
deck.js
jde
methodology
nslocalizedstring
google-app-engine-php
clear
javapackager
tess4j
vensim
euro
maven-archetype
perfect-scrollbar
chunks
iphone-6
illegalargumentexception
clearcanvas
sync
azure-worker-roles
twitter-finagle
lettuce
internet-radio
mahara
mysql-error-1146
lastinsertid
svg-android
aspnet-compiler
typography
friendly-url
wpd
backbone-views
proj4
symbian3
ftpwebrequest
generator-expression
linqdatasource
quit
aspmenu-control
jquery-ui-map
diazo
scsf
mcpd
cherokee
vectorwise
lightopenid
jexcelapi
nyromodal
time-management
authkit

Resources

Encrypt Message