【问题标题】:Getting error "Argument of type 'typeof Header' is not assignable to parameter of type 'ComponentType...' or 'StatelesComponent'..."出现错误“'typeof Header' 类型的参数不可分配给 'ComponentType...' 或 'StatelesComponent' 类型的参数...”
【发布时间】:2018-08-19 10:22:12
【问题描述】:

首先,我对 React 世界比较陌生,在我职业生涯的大部分时间里都编写了大量 API。我正在为非营利组织构建一个 React 应用程序,而我只是在尝试起步。

我添加了一个头类如下:

import './header.css';
import * as React from 'react';
import * as actions from '../../actions/authenticationActions';
import { AppState } from '../../state/appState';
import { connect, Dispatch } from 'react-redux';

const logo = require('./logo.svg');

interface Props {
    displayName: string;
    isAuthenticated: boolean;
    logIn?: () => void;
    logOut?: () => void;
}

interface State {

}
class Header extends React.Component<Props, State> {
    constructor(props: Props, state: State) {
        super(props, state);
    }

    render() {
        return (
            <div className={'Header'}>
                <div className={'Container'}>
                    <img src={logo} className="App-logo" alt="logo" />
                    <div className={'Header__nav'}>
                        <div className={'userLogin'}>
                            <div className={'user'}>{this.props.displayName}</div>
                            <a onClick={this.props.logOut}>Log Out</a><a onClick={this.props.logIn}>Log In</a>
                        </div>
                        {/*<a href='https://localhost/' className={'button button--goBack'}>Back to Website</a>*/}
                    </div>
                </div>
            </div>
        );
    }
}

export const mapStateToProps = ({ currentUser }: AppState) => ({
    displayName: (currentUser != null ? currentUser.preferredName : 'Please Log In'),
    isAuthenticated: currentUser != null
});

export const mapDispatchToProps = (dispatch: Dispatch<actions.AuthenticationActions>) => ({
    logIn: () => dispatch(actions.logIn()),
    logOut: () => dispatch(actions.logOut())
});

export default connect(mapStateToProps, mapDispatchToProps)(Header);

这在很大程度上似乎没问题,但由于以下错误消息而无法编译:

“typeof Header”类型的参数不能分配给参数 类型'组件类型 登录;登出: ...'。类型'typeof Header'不是 可分配给类型 'StatelessComponent 登录;日志...'。 类型 'typeof Header' 提供不匹配的签名 '(props: { displayName: string; isAuthenticated: boolean; } & { logIn: () => 登录;登出:() => 登出; } & { 孩子?:反应节点; }, 语境?: 任何):反应元素 |空'。

我已经为此奋斗了几个小时,但无济于事。我相当有信心这是一个菜鸟错误;请温柔一点!

【问题讨论】:

    标签: reactjs typescript react-redux


    【解决方案1】:

    构造函数中的第二个参数不是State,而是上下文。

    Header 不是有效的 React.Component 因为构造函数应该是

    constructor(props: Props, context) {
        super(props, context);
    }
    

    或者只是

    constructor(props: Props) {
        super(props);
    }
    

    除非您需要某些内容的上下文。

    也就是说,您使用React.Component&lt;Props, State&gt; 正确键入了它,因为这两种类型是通用React.Component 类型所期望的,但这两种类型并不反映构造函数参数应该是什么(即@987654325 @ 和(可选)context)

    【讨论】:

    • 感谢您的快速回复!我完全从等式中删除了 State 到你写的方式..但我仍然遇到同样的错误。还有什么突出的吗?
    • 不,通用定义是正确的。现在,您实际上并没有使用 State,因此您可以将其从泛型类型定义中删除,但如果您使用 state,因此您的 State 接口有属性,那么你实现它的方式是正确的。
    • 确保是完全相同的错误。 TypeScript 可以为 React 组件提供非常详细的(因此难以区分)类型错误。通常错误中的最后一行有需要解决的具体问题。
    • “typeof Header”类型的参数不能分配给“ComponentType 登录;登出: ...'。类型 'typeof Header' 不可分配给类型 'StatelessComponent 登录;日志...'。类型 'typeof Header' 不匹配签名 '(props: { displayName: string; isAuthenticated: boolean; } & { logIn: () => LogIn; logOut: () => LogOut; } & { children?: ReactNode ; }, context?: any): ReactElement |空'。
    • 您在尝试连接时是否收到此错误? (例如,它是由您的示例中的最后一行引起的)?还是尝试在 JSX 中实际使用 Header? (例如来自
    【解决方案2】:

    这个错误让 connect 看起来真的非常期待一个无状态组件(尽管我不确定为什么)。你可以试试:

    import './header.css';
    import * as React from 'react';
    import * as actions from '../../actions/authenticationActions';
    import { AppState } from '../../state/appState';
    import { connect, Dispatch } from 'react-redux';
    
    const logo = require('./logo.svg');
    
    interface Props {
      displayName: string;
      isAuthenticated: boolean;
      logIn?: () => void;
      logOut?: () => void;
    }
    
    const Header = (props: Props) => (
      <div className={'Header'}>
        <div className={'Container'}>
          <img src={logo} className="App-logo" alt="logo"/>
          <div className={'Header__nav'}>
            <div className={'userLogin'}>
              <div className={'user'}>{props.displayName}</div>
              <a onClick={props.logOut}>Log Out</a><a onClick={props.logIn}>Log In</a>
            </div>
            {/*<a href='https://localhost/' className={'button button--goBack'}>Back to Website</a>*/}
          </div>
        </div>
      </div>
    );
    
    export const mapStateToProps = ({currentUser}: AppState) => ({
      displayName: (currentUser != null ? currentUser.preferredName : 'Please Log In'),
      isAuthenticated: currentUser != null
    });
    
    export const mapDispatchToProps = (dispatch: Dispatch<actions.AuthenticationActions>) => ({
      logIn: () => dispatch(actions.logIn()),
      logOut: () => dispatch(actions.logOut())
    });
    
    export default connect(mapStateToProps, mapDispatchToProps)(Header);
    

    【讨论】:

    • 加载...这让我很紧张,因为理想情况下我将使用状态来保存“isAuthenticated”属性,并且因为我不知道为什么它需要一个无状态组件。跨度>
    • 一般来说,我喜欢 Typescript。 Redux 的 connect 实现可能对生产力非常非常有害,因为它们是如何连接 connect 的。也就是说,我的团队遵循了一种做法,以准确防止您遇到的错误类型。 gist.github.com/JaSpr/502084fd5989b53760d93148cf67d864
    • 通过为我的 mapStateToProps 和 mapDispatchToProps 提供类型,我能够准确地告诉 typescript 我将要连接的组件的外观。否则(如您的情况)打字稿会尝试根据基于这两个映射函数的最佳猜测来推断您传入的组件(标题)将是什么样子。您可以预先提供的信息越多(使用 MapStateToProps 和 MapDispatchToProps)越好
    • 是的!这太棒了!在玩弄了要点之后,我真正编译并运行了它!太感谢了!我不确定我是否可以通过微小的变化来更新要点并充实那些东西......现在看。这是一个很好的做法。我喜欢它!建立标准的最佳时机。
    猜你喜欢
    • 2020-01-06
    • 2018-05-15
    • 2021-03-01
    • 2019-12-19
    • 1970-01-01
    • 1970-01-01
    • 2020-09-24
    • 1970-01-01
    • 2021-10-29
    相关资源
    最近更新 更多