使用重构来映射从上下文中消耗的道具

问题描述 投票:2回答:2

我有一个功能组件,需要渲染道具heightwidth。我们称之为PureSizableDiv

const PureSizableDiv = ({ height, width }) =>
    <div style={{ height, width }}>I'm a div!</div>

我还有一个名为Size的React上下文:

import React from 'react';
import { compose, fromRenderProps } from 'recompose';

export const { SizeProvider, SizeConsumer } = React.createContext({
  height: null,
  width: null,
});

而不是像这样手动创建一个新的HoC:

export const withSize = Component => (props) =>
  <SizeConsumer>
    {
      ({ height, width }) =>
        <Component
          height={height}
          width={width}
          {...props}
        />
    }
  </SizeConsumer>; 

我想知道使用recompose这样做是否有更短的清洁方式。我试过了

export const withSize = compose(
  fromRenderProps(SizeConsumer, ({ height, width }) => ({ height, width })),
);

但得到了错误Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

javascript reactjs higher-order-components recompose react-context
2个回答
2
投票

我已连接我的组件,但我没有正确使用Context API。我修复了代码,并使用fromRenderPropsrecompose完美运行。工作代码:

import React from 'react';
import { compose, fromRenderProps } from 'recompose';

const PureSizableDiv = ({ height, width }) =>
  <div style={{ height, width }}>I am a div!</div>;

const SizeContext = React.createContext({
  height: null,
  width: null,
});

const withSize = compose(
  fromRenderProps(SizeContext.Consumer, ({ height, width }) => ({ height, width })),
);

// Usage
const Wrapper = ({ children, height, width }) => 
  <SizeContext.Provider
    value={{
      height: height,
      width: width,
    }}
  >
    {children}
  </SizeContext.Provider>;

const SizedDiv = withSize(PureSizableDiv);

// Render components
<Wrapper>
  <SizedDiv/>
</Wrapper>

1
投票

您可能忘记从其定义的文件中导出组件,或者您可能混淆了默认导入和命名导入。

出现错误是因为您没有使用compose导出Component:

export const withSize = compose(
  fromRenderProps(SizeConsumer, ({ height, width }) => ({ height, width })),
)(Component);
// ^^
© www.soinside.com 2019 - 2024. All rights reserved.