键入与Redux连接的HOC组件

时间:2019-05-27 09:59:46

标签: reactjs typescript redux react-router

在我的Route组件中,我有一个Layout HOC,其中包含一些子组件。在此HOC中,我渲染了顶部和侧面栏,并且还将他连接到我的redux商店以获取当前用户并调度注销操作。问题是我定义了我的Hoc's Props,并将子代作为ReactNode,将用户作为UserType并将注销操作作为函数。但是在Route组件中,我收到一个错误,因为a没有将用户和操作作为道具传递。

我的HOC组件

interface Props extends RouteComponentProps {
  children?: ReactNode
  user?: UserType
  logoutAction(): void
}

const AppLayout = (props: Props) => (
  <Layout>
    {/* <Sidebar {...props} /> */}
    <Layout>
      {/* <TopBar user={props.user} /> */}
      <Content
        style={{
          margin: '24px 16px',
          padding: 24,
          background: '#fff',
          minHeight: 280
        }}
      >
        {props.children}
      </Content>
    </Layout>
  </Layout>
)
const mapStateToProps = (state: AppStateType, ownProps: Props) => ({
  ...ownProps,
  user: state.auth.currentUser
})

const mapDispatchToProps = (dispatch: Dispatch) => ({
  logoutAction: () => dispatch(logoutUserSuccessAction())
})

export default withRouter(
  connect(
    mapStateToProps,
    mapDispatchToProps
  )(AppLayout)
)

我的路线组件

class Routes extends React.Component<Props> {
  componentDidMount = () => {
    this.props.fetchFields()
    // this.props.fetchQuestions();
  }

  render() {
    return (
      <div
        style={{
          display: 'flex',
          height: '100vh',
          flexDirection: 'column',
          width: '100vw'
        }}
      >
        <AppLayoutContainer>
          <React.Fragment>
            <Switch>
              <Route path="/" exact component={HomePageContainer} />

              <Route path="/login" exact component={LoginPageContainer} />
              {/* NEED AUTH HOC */}
              <Route path="/gerencia" component={GerenciaPageContainer} />
              <Route path="/relatorio" component={ReportPageContainer} />
              <Route path="/exportar" component={ExportPageContainer} />
            </Switch>
          </React.Fragment>
        </AppLayoutContainer>
      </div>
    )
  }
}

我得到的错误:

Property 'logoutAction' is missing in type '{ children: Element; }' but required in type 'Readonly<Pick<Pick<Props, never> & Props, "user" | "children" | "logoutAction">>'.ts(2741)
AppLayoutContainer.tsx(20, 3): 'logoutAction' is declared here.

我正在尝试键入connect函数,但出现其他错误:

interface OwnProps extends RouteComponentProps {
  children?: ReactNode
  // user?: UserType
}

interface StateProps {
  user?: UserType
}

interface DispatchProps {
  logoutAction: () => void
}

type Props = StateProps & DispatchProps & OwnProps

const AppLayout = (props: Props) => (
  <Layout>
    {/* <Sidebar {...props} /> */}
    <Layout>
      {/* <TopBar {...props} /> */}
      <Content
        style={{
          margin: '24px 16px',
          padding: 24,
          background: '#fff',
          minHeight: 280
        }}
      >
        <Button onClick={() => props.logoutAction()}>Fazer Logout</Button>
        {props.children}
      </Content>
    </Layout>
  </Layout>
)

function mapStateToProps(
  state: AppStateType,
  ownProps: OwnProps
): StateProps & OwnProps {
  // ...ownProps,
  return {
    ...ownProps,
    user: state.auth.currentUser
  }
}

const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => ({
  logoutAction: () => dispatch(logoutUserSuccessAction())
})

export default connect<StateProps, DispatchProps, void>(
  mapStateToProps,
  mapDispatchToProps
)(AppLayout)

我现在收到此错误:

Argument of type '(state: { auth: AuthReducerStateType; }, ownProps: OwnProps) => StateProps & OwnProps' is not assignable to parameter of type 'MapStateToPropsParam<StateProps, void, {}>'.
  Type '(state: { auth: AuthReducerStateType; }, ownProps: OwnProps) => StateProps & OwnProps' is not assignable to type 'MapStateToPropsFactory<StateProps, void, {}>'.
    Types of parameters 'state' and 'initialState' are incompatible.
      Property 'auth' is missing in type '{}' but required in type '{ auth: AuthReducerStateType; }'.ts(2345)
getReducers.ts(41, 3): 'auth' is declared here.

1 个答案:

答案 0 :(得分:1)

因此logoutAction由redux提供,而不是由您手动提供。

您已根据需要将此道具标记为。 Typescript不知道它是redux组件,并且会基于mapDispatchToProps传递此道具,因此它抱怨您没有提供它

在这种情况下,当外部lib(在您的情况下为redux)提供某些道具时,我通常将其标记为可选(这是有道理的,因为您实际上无法控制该道具的传递)

interface Props extends RouteComponentProps {
  children?: ReactNode
  user?: UserType
  logoutAction()?: void // <<<--- ? added
}

应该解决问题