React / TypeScript:通过HOC消耗上下文

我正在尝试在TypeScript(2.8)中使用React文档(React

16.3)中的HOC来实现示例使用上下文,并且失败了。作为参考,React手册中的代码:

const ThemeContext = React.createContext('light');

// This function takes a component...

export function withTheme(Component) {

// ...and returns another component...

return function ThemedComponent(props) {

// ... and renders the wrapped component with the context theme!

// Notice that we pass through any additional props as well

return (

<ThemeContext.Consumer>

{theme => <Component {...props} theme={theme} />}

</ThemeContext.Consumer>

);

};

}

我能想到的最好的方法是:

export interface ThemeAwareProps {

theme: string;

}

const ThemeContext = React.createContext('light');

export function withTheme<P extends ThemeAwareProps, S>(Component: new() => React.Component<P, S>) {

return function ThemedComponent(props: P) {

return (

<ThemeContext.Consumer>

{theme => <Component {...props} theme={theme} />}

</ThemeContext.Consumer>

);

};

}

class App extends React.Component {

public render() {

return (

<ThemeContext.Provider value={'dark'}>

<ThemedButton/>

</ThemeContext.Provider>

);

}

}

ThemedButton.tsx:

interface ThemedButtonProps extends ThemeAwareProps {

}

interface ThemedButtonState{

}

class ThemedButton extends React.Component<ThemedButtonProps, ThemedButtonState> {

constructor(props: ThemedButtonProps) {

super(props);

}

public render() {

return (

<button className={this.props.theme}/>

)

}

}

export default withTheme(ThemedButton);

问题是最后一行(export default withTheme(ThemedButton))。TypeScript编译器抱怨

类型的typeof ThemedButton参数不能分配给类型的参数new () => Component<ThemedButtonProps,

ThemedButtonState, any>

我想念什么?

回答:

您大部分情况都是正确的,但缺少一些内容:

  1. 对于Component,请使用React.ComponentType<Props>,它正确接受类组件和功能组件。我认为new () => ...单独使用在这里不起作用,因为签名不能完全匹配。

  2. ThemedButton在使用道具时将其排除在外,您必须使用一些看起来很神奇的语法:

    function ThemedComponent(props: Pick>)

这是这样做的:

  • Exclude<keyof P, keyof ThemeAwareProps>表示“获取的密钥P,然后拿走其中的密钥ThemeAwareProps
  • Pick<P, ...>然后说:“从P,仅返回具有这些属性的对象类型”

将这些结合起来,便得到了一个组件,它接受所有可以做的道具ThemedButton,减去theme道具,这样我们就可以做到<ThemedButton

/>没有错误。

这是完整的HOC:

function withTheme<P extends ThemeAwareProps>(Component: React.ComponentType<P>) {

return function ThemedComponent(props: Pick<P, Exclude<keyof P, keyof ThemeAwareProps>>) {

return (

<ThemeContext.Consumer>

{(theme) => <Component {...props} theme={theme} />}

</ThemeContext.Consumer>

)

}

}

最后,关于该主题的一篇不错的博客文章,我从中收集了大部分此类信息。如果您愿意,它还包括一种缩短类型的Pick<...>内容的方法Omit


编辑:休息/传播的行为已在3.2中更改,并且此错误作为不幸的副作用出现,导致props与其他道具合并时被擦除的类型。当前可行的解决方法是强制转换propsP

    return (

<ThemeContext.Consumer>

{(theme) => <Component {...props as P} theme={theme} />}

</ThemeContext.Consumer>

)

以上是 React / TypeScript:通过HOC消耗上下文 的全部内容, 来源链接: utcz.com/qa/407398.html

回到顶部