In this post I'll briefly describe small refactoring of React component based on this article
I'm creating an SPA using React and Redux library for Flux architecture.
MyComponent - old way
MyComponent.js
import React, { Component, PropTypes } from 'react'import { connect } from 'react-redux'import { myAction } from '../actions' // actionsimport styles from './styles.scss' // CSS Modules
class MyComponent extends Component { render() { return (<div className={styles.myClass}>MyComponent...</div>) }}
MyComponent.propTypes = { propFromUrlParam: PropTypes.string.isRequired, propFromState: PropTypes.string.isRequired, myAction: PropTypes.func.isRequired}
function mapStateToProps(state, props) { let { propFromUrlParam } = props.params; // props from URL params let { propFromState } = state; // props from state return {propFromUrlParam, propFromState}}
export default connect(mapStateToProps, { // mapping methods to component myAction})(MyComponent)This file is going to be really big and one of best practices is to divide it into two logical parts:
Dumb and Smart or Container and Presentational components. All the explanation you can find here.
I'll just show how it looks in my case after dividing. So,
MyComponent - new way
MyComponent.js the presentational component:
import React, { Component, PropTypes } from 'react'import styles from './styles.scss' // CSS Modules
class MyComponent extends Component { render() { return (<div className={styles.myClass}>MyComponent...</div>) }}
MyComponent.propTypes = { propFromUrlParam: PropTypes.string.isRequired, propFromState: PropTypes.string.isRequired, myAction: PropTypes.func.isRequired}
export default MyComponentMyComponentContainer.js the container component:
import MyComponent from './MyComponent' // presentational componentimport { connect } from 'react-redux'import { bindActionCreators } from 'redux'import { myAction } from '../actions' // actions
function mapStateToProps(state, props) { let { propFromUrlParam } = props.params; // prop from URL params let { propFromState } = state; return {propFromUrlParam, propFromState}}
function mapDispatchToProps(dispatch) { return { ...bindActionCreators({ // mapping methods to component myAction }, dispatch) }}
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);And a small helper index.js which is used just for convenience while importing the component and looks like this:
export default from './MyComponent' // container componentsNow you may import the MyComponent wherever you need it
import MyComponent from './components/MyComponent' // will import index.js
