Reputation: 14821
I am starting to develop a web application using React JS. I bought a theme from theme forest. In the theme, they are using compose like this in the component.
...Other code here
Login.propTypes = {
classes: PropTypes.shape({}).isRequired,
width: PropTypes.string.isRequired
};
export default compose(withWidth(), withStyles(themeStyles, { withTheme: true }))(Login);
As you can see their code is using the compose at the end when exporting the Component. I cannot modify their built-structure. What I like to do now is I like to use connect feature of the react as well.
Normally connect is used in the place of compose. Now, if I want to use connect to work with the state of the application, how can I use it together with compose ?
Upvotes: 27
Views: 27845
Reputation: 329
I was receiving the following error while using compose
with Typescript:
JSX element type 'App' does not have any construct or call signatures. TS2604
I had to add ComponentType
in the following way to make it work:
export default compose<ComponentType>(withTranslation(), connect(mapStateToProps, mapDispatchToProps))(App);
Upvotes: 3
Reputation: 21
import {connect} from "react-redux";
import {compose} from 'redux'
class BookList extends Component {
componentDidMount() {
const {bookstoreService} = this.props;
const data = bookstoreService.getBooks();
this.props.booksLoaded(data);
}
render() {
const {books} = this.props;
return (
<ul>
{books.map(book => {
return (
<li key={book.id}>
<BookListItem book={book}/>
</li>
);
})}
</ul>
);
}
}
const mapStateToProps = ({books}) => {
return {books};
};
const mapDispatchToProps = dispatch => {
return {
booksLoaded: newBooks => {
dispatch(booksLoaded(newBooks));
}
};
};
export default compose(withBookstoreService(), connect(mapStateToProps, mapDispatchToProps))(BookList);
Upvotes: 2
Reputation: 14725
compose
doesn't get rid of the pattern of passing a function to the result of a function call, but it reduces its use to one.
Only one HOC, no gain from using compose:
// withStyles, without compose
export default withStyles(styles)(MyComponent)
// withStyles, with compose
export default compose(withStyles(styles))(MyComponent)
// connect, without compose
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)
// connect, with compose
export default compose(connect(mapStateToProps, mapDispatchToProps))(MyComponent)
Note that starting another function call immediately after a function call, which only recently came into fashion, is still there with compose
.
With two HOCs there is a gain from compose
because the nesting of parens is less:
// two HOCs, without compose
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(MyComponent))
// two HOCs, with compose
export default compose(connect(mapStateToProps, mapDispatchToProps), withStyles(styles))(MyComponent)
This still can be hard to follow if you aren't used to a nameless function being called immediately after it's created. If you prefer you can give a name to it:
// two HOCs, with compose
const enhance = compose(connect(mapStateToProps, mapDispatchToProps, withStyles(styles));
// export default enhance(MyComponent);
I prefer to use compose when there is more than one HOC, and to use it directly. I think cutting down on the nesting is useful but giving it a generic name like enhance
is unnecessary.
Upvotes: 7
Reputation: 1095
import {bindActionCreators} from 'redux';
import compose from 'recompose/compose';
import { connect } from 'react-redux';
...Other code here
function mapStateToProps(state) {
return {
//return state
}
}
function mapDispatchToProps(){
return bindActionCreators({
//actions
}, dispatch);
}
Login.propTypes = {
classes: PropTypes.shape({}).isRequired,
width: PropTypes.string.isRequired
};
export default compose(withWidth(), withStyles(styles, {withTheme: true}), connect(mapStateToProps, mapDispatchToProps))(Login);
I hope this solves your problem.
Upvotes: 7
Reputation: 1170
const enhance = compose(
withRouter,
withStyles(styles, 'some style'),
connect(mapStateToProps, mapDispatchToProps),
....
export default enhance(MyComponent);
Upvotes: 37