在反应干中略微调整了HOC

时间:2018-11-16 11:01:21

标签: javascript reactjs

我有一个简单的HOC,它在包装的组件中注入了一个反应上下文作为道具。

function withTranslate(WrappedComponent) {
//we forward the ref so it can be used by other 
  return React.forwardRef((props, ref) => ( 
    <TranslatorContext.Consumer>
      {context => (<WrappedComponent {...props} translate={context} ref={ref} />)}
    </TranslatorContext.Consumer>)
  )
}

现在,我想要一个使用相同上下文的辅助HOC,但是使用该上下文更改一些预定义的props。我成功完成以下代码:

export function withTranslatedProps(WrappedComponent,propsToBeTransLated) {
        //propsToBetranslated is array with all props which will be given via keys
        const translateProps=(translate,props)=>{
            const ownProps=Object.assign({},props)
            propsToBeTransLated.forEach(p=>{
                if(ownProps.hasOwnProperty(p)){
                    ownProps[p]=translate(ownProps[p])
                }
            })
            return ownProps
        }
        return React.forwardRef((props, ref) => {
            console.log("render contextconsumer")
            return (
                <TranslatorContext.Consumer>
                    {context => (
                        <WrappedComponent {...translateProps(context,props)} ref={ref} />
                    )}
                </TranslatorContext.Consumer>)
        })
    }

但是我几乎完全使用与withTranslate相同的HOC。有没有更好的选择(无需重复自己)?

编辑 我想我解决了:

const _translateProps=(propsToBeTransLated,translate,props)=>{
            const ownProps=Object.assign({},props)
            propsToBeTransLated.forEach(p=>{
                if(ownProps.hasOwnProperty(p)){
                    ownProps[p]=translate(ownProps[p])
                }
            })
            return ownProps
        }
    export function withTranslatedProps(WrappedComponent,propsToBeTransLated) {
        //propsToBetranslated is array with all props which will be given via keys
        let retrieveProps=propsToBeTransLated?_translateProps.bind(null,propsToBeTransLated):(context,props)=>({translate:context,...props})
        return React.forwardRef((props, ref) => {
            console.log("render contextconsumer")
            return (
                <TranslatorContext.Consumer>
                    {context => (
                        <WrappedComponent {...retrieveProps(context,props)} ref={ref} />
                    )}
                </TranslatorContext.Consumer>)
        })
    }

有其他可能更好的解决方案的人吗?

1 个答案:

答案 0 :(得分:1)

您可以通过Translate HOC重复使用,也可以使用相同的HOC添加选项。

与Translate HOC一起使用:

/* function that translate the propsToBeTransLated */
const translateProps = (propsToBeTransLated, translate, props) => 
  propsToBeTransLated.reduce((translatedProps, prop) => {
    if(props.hasOwnProperty(prop))
      translatedProps[prop] = translate(props[prop]);

    return translatedProps;
  }, {});

export function withTranslatedProps(WrappedComponent, propsToBeTransLated = []) {
  // HOC inside HOC
  const addTranslationsToProps = WrappedComponentWithContext =>
    React.forwardRef((props, ref) => (
      <WrappedComponentWithContext
        {...props}
        {...translateProps(propsToBeTransLated, props.translate, props)}
        ref={ref}
      />
    )
  );

  // first call withTranslate to add the context
  return addTranslationsToProps(withTranslate(WrappedComponent));
}

向withTranslate HOC添加选项

const translateProps = (propsToBeTransLated, translate, props) =>
  propsToBeTransLated.reduce((translatedProps, prop) => {
    if(props.hasOwnProperty(prop))
      translatedProps[prop] = translate(props[prop]);

    return translatedProps;
  }, {});

export function withTranslate(WrappedComponent, options) {
  const { propsToBeTransLated = [] } = options;
  return React.forwardRef((props, ref) => (
    <TranslatorContext.Consumer>
      {context => (
        <WrappedComponent
          {...props}
          {...translateProps(propsToBeTransLated, context, props)}
          translate={context}
          ref={ref}
        />
      )}
    </TranslatorContext.Consumer>
  ));
}