反应结合不同包装

时间:2018-06-25 14:39:13

标签: javascript reactjs react-redux graphql i18next

我们正在React中启动一个新项目。 我们需要使用:

  • 反应上下文API
  • i18n(react.i18nex)
  • GraphQL(Apollo客户端)
  • Redux
  • JS中的CCS-in-JS(样式化组件或磷灰石)

问题是该实现中的任何一个都包装了一个组件并将其传递一些道具或将功能用作子代。

我想使组件保持脱开状态并尽可能清洁。

如何构造包装器?

示例

首页

<Home {...props} />

上下文:

 <ThemeContext.Consumer>
   { theme=> <Home {...theme} programa={theme} /> }
 </ThemeContext.Consumer>

i18n:

 <I18n>
    {t => <Home text={t("translated text")} /> }
 </I18n>

GraphQL:

<Query query={GET_PROGRAMA}>
  {({ data }) => <Home data={data} />}
</Query>

Redux:

const mapStateToProps = state => ({
    user: "some user"
});


export default connect(
  mapStateToProps,
)(Home);

如您所见,Home组件从许多来源接收隔离的道具。

我该如何管理ir并使它解耦?有某种 composer

谢谢!

2 个答案:

答案 0 :(得分:1)

我认为您可以将其转换为可以为您处理所有组件包装的HOC:

const withWrappers = WrappedComponent => {
  return class extends React.Component {
    render () {
      return (
        <ThemeContext.Consumer>
          { theme =>
            <I18n>
              { t =>
                <Query query={GET_PROGRAMA}>
                  { ({ data }) => 
                    <WrappedComponent
                      {...this.props}
                      {...theme}
                      programa={theme}
                      data={data}
                      text={t("translated text")}
                    />
                  }
                </Query>
              }
            </I18n>
          }
        </ThemeContext.Consumer>
      )
    }
  }
}

用法:

class Home extends React.Component {
    render () {
      return (
        <div>Home</div>
      )
    }
}

export default withWrappers(Home);

答案 1 :(得分:0)

感谢您的帮助!你们所有人 我已经实现了一个HOC,与您提出的相同,并且将GraphQL组件保留在外部:

import React from "react";
import PropTypes from "prop-types";
import { mergeStyles } from "js/utils";
import { I18n } from "react-i18next";
import { TemplateContext } from "js/template-context";

const Wrapper = ({ Component, getStylesFromTemplate }) => props => {
  const { classes } = props;
  return (
    <TemplateContext.Consumer>
      {programa => {
        const { template } = programa;
        const stylesFromTemplate = getStylesFromTemplate(template);
        const styles = mergeStyles({ classes, stylesFromTemplate });
        return (
          <I18n>
            {(t, { i18n }) => {
              return (
                <Component
                  t={t}
                  styles={styles}
                  programa={programa}
                  {...props}
                />
              );
            }}
          </I18n>
        );
      }}
    </TemplateContext.Consumer>
  );
};

Wrapper.propTypes = {
  classes: PropTypes.object.isRequired
};

export default Wrapper;

再次感谢您!