Используя compose() и connect() вместе в React JS redux

Я начинаю разрабатывать веб-приложение с использованием React JS. Я купил тему из тематического леса. В теме они используют компоновку, подобную этой в компоненте.

...Other code here
 Login.propTypes = {
      classes: PropTypes.shape({}).isRequired,
      width: PropTypes.string.isRequired
    };

    export default compose(withWidth(), withStyles(themeStyles, { withTheme: true }))(Login);

Как вы можете видеть, их код использует compose в конце при экспорте Component. Я не могу изменить их встроенную структуру. То, что мне нравится делать сейчас, я тоже люблю использовать функцию соединения.

Обычно соединение используется в месте компоновки. Теперь, если я хочу использовать соединение для работы с состоянием приложения, как я могу использовать его вместе с compose?

Ответ 1

const enhance = compose(
    withRouter,
    withStyles(styles, 'some style'),
    connect(mapStateToProps, mapDispatchToProps),
    ....

export default enhance(MyComponent);

Ответ 2

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);

Надеюсь, это решит вашу проблему.

Ответ 3

compose не избавляется от шаблона передачи функции в результате вызова функции, но сокращает ее использование до единицы.

Только один HOC, никакой выгоды от использования 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)

Обратите внимание, что запуск другого вызова функции сразу после вызова функции, который только недавно вошел в моду, все еще существует в compose.

С двумя HOC есть преимущество от compose потому что вложенность parens меньше:

// 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)

Это все еще может быть трудно понять, если вы не привыкли к безымянной функции, вызываемой сразу после ее создания. Если вы предпочитаете, вы можете дать ему имя:

// two HOCs, with compose
const enhance = compose(connect(mapStateToProps, mapDispatchToProps, withStyles(styles));
// export default enhance(MyComponent);

Я предпочитаю использовать compose, когда имеется более одного HOC, и использовать его напрямую. Я думаю, что сокращение вложения полезно, но давать ему общее имя, например, enhance не нужно.

Ответ 4

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);