TypeScript将React-Redux装饰器与有状态组件连接起来

Tom*_*uer 2 typescript reactjs redux react-redux

我已经创建了一个说明性组件Hello,我尝试使用适当的类型props,state同时使用connectReact-Redux中的装饰器.

您可以在我创建的GitHub存储库中进行演示来说明这一点.

如果connect没有用作装饰,而是,export default connect(mapStateToProps, mapDispatchToProps)(Hello)使用和组件本身没有出口,这个工程.

type HelloStateProps = { enthusiasmLevel: number; };
type HelloDispatchProps = { incrementEnthusiasm: () => void; decrementEnthusiasm: () => void; };
type HelloOwnProps = { name: string; };
type HelloProps = HelloStateProps & HelloDispatchProps & HelloOwnProps;
type HelloState = { useHi: boolean; };

// I am getting an error here
@connect(mapStateToProps, mapDispatchToProps)
export default class Hello extends React.Component<HelloProps, HelloState> {
  state: HelloState = { useHi: false };

  onChangeGreetingButtonClick: React.MouseEventHandler<HTMLButtonElement> = event =>
    this.setState(state => ({ useHi: !state.useHi }))

  render() {
    const { useHi } = this.state;
    const { name, enthusiasmLevel } = this.props;
    return (
      <div className="hello">
        {useHi ? 'Hi' : 'Hello'} {name} x{enthusiasmLevel}
        <div>
          <button onClick={this.props.decrementEnthusiasm}>-</button>
          <button onClick={this.props.incrementEnthusiasm}>+</button>
          <button onClick={this.onChangeGreetingButtonClick}>Change greeting</button>
        </div>
      </div>
    );
  }
}

export function mapStateToProps({ enthusiasmLevel }: StoreState): HelloStateProps {
  return { enthusiasmLevel };
}

export function mapDispatchToProps(dispatch: Dispatch<EnthusiasmAction>): HelloDispatchProps {
  return Redux.bindActionCreators({ incrementEnthusiasm, decrementEnthusiasm }, dispatch);
}
Run Code Online (Sandbox Code Playgroud)

我尝试connect用作装饰器时遇到的错误如下:

Unable to resolve signature of class decorator when called as an expression.
  Type 'ComponentClass<Pick<HelloProps, "name">> & { WrappedComponent: ComponentType<HelloProps>; }' is not assignable to type 'typeof Hello'.
    Type 'Component<Pick<HelloProps, "name">, ComponentState>' is not assignable to type 'Hello'.
      Types of property 'state' are incompatible.
        Type 'Readonly<ComponentState>' is not assignable to type 'HelloState'.
          Property 'useHi' is missing in type 'Readonly<ComponentState>'.
Run Code Online (Sandbox Code Playgroud)

当我完全剥离状态组件时,如下所示:

@connect(mapStateToProps, mapDispatchToProps)
export default class Hello extends React.Component<HelloProps> {
  render() {
    const { name, enthusiasmLevel } = this.props;
    return (
      <div className="hello">
        Hi {name} x{enthusiasmLevel}
        <div>
          <button onClick={this.props.decrementEnthusiasm}>-</button>
          <button onClick={this.props.incrementEnthusiasm}>+</button>
        </div>
      </div>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

...我得到了这个错误:

Unable to resolve signature of class decorator when called as an expression.
  Type 'ComponentClass<Pick<HelloProps, "name">> & { WrappedComponent: ComponentType<HelloProps>; }' is not assignable to type 'typeof Hello'.
    Type 'Component<Pick<HelloProps, "name">, ComponentState>' is not assignable to type 'Hello'.
      Types of property 'render' are incompatible.
        Type '() => string | number | false | Element | Element[] | ReactPortal | null' is not assignable to type '() => Element'.
          Type 'string | number | false | Element | Element[] | ReactPortal | null' is not assignable to type 'Element'.
            Type 'null' is not assignable to type 'Element'.
Run Code Online (Sandbox Code Playgroud)

问题出在哪儿?我不明白错误信息.

在有状态的,state应该做出0差异connect,对吧?那为什么甚至报道呢?并且useHi绝对不会错过ReadOnly<HelloState>,但是从何ComponentState而来?

在无状态的一个,render当盘旋时,显示JSX.Element返回类型.那又怎么样null呢?

Gab*_*leu 7

似乎是一个悬而未决的问题.

上面列出的几种解决方法如下:

@(connect(mapStateToProps, mapDispatchToProps) as any)
Run Code Online (Sandbox Code Playgroud)

  • 谢谢。我建议人们坚持使用“导出默认连接”,而不是使用该解决方法,因为这会破坏 JSX 中组件的“props”类型。 (2认同)