打字稿帮助-使用HOC覆盖react-redux connect()

时间:2019-09-20 11:21:09

标签: javascript typescript react-redux

希望一些Typescript专家可以帮助我,因为我是新手。

我正在尝试使用react-redux将组件状态存储到redux中,我遇到的一个问题是我需要一种组织可重用组件的方法,以使它们在全局存储中的状态不会相互干扰。

我受到https://github.com/eloytoro/react-redux-uuid的启发,该提议建议使用安装时随机生成的UUID将组件的状态自动注册到全局存储中,将状态存储在该“切片”中,并在卸载时将其从redux中删除。连接时,它将在mapStatetoProps中向组件显示组件状态数据的“切片”。但是,该库已失效且不符合Typescript。

我已经修改了代码,因此使用起来很容易:

  • AdminUserListContainer.tsx [状态存储在redux中的可重用组件]
import { connectUUID,IRedux_UUID_DispatchProps } from 'lib/Redux_UUID';

export type TAdminUserListReduxState = {
  loadStatus:string,
  user_list:{user_list:any[]},
  loadErrorDesc:string
}
export interface AdminUserListProps {
  company_id:number,
  userClickPath:string
}
export const AdminUserListContainer:FunctionComponent<AdminUserListProps & TAdminUserListReduxState & IRedux_UUID_DispatchProps> = (props) => {
...
     props.dispatchUUID({
        type: 'SOME_ACTION',
        payload: {
          action_param1: param1;
        }
      });
...
};

const mapStateToProps = (state:{localState:TAdminUserListReduxState,globalState:any}) => {
  return state.localState;
};

export default connectUUID('AdminUserListContainer',mapStateToProps)(AdminUserListContainer);

我基本上使用我自己的connectUUID()覆盖react-redux中的connect(),这将实现HOC,该HOC进行UUID注册/取消注册+切片特定于组件的状态以传递到mapStateToProps中的props中(这个想法是来自react-redux-uuid库)。为简化起见,我不使用动作创建者,所以不使用分派映射,而是使用dispatchUUID({action})直接分派动作(此分派会将UUID注入到动作中,以便减速器知道要减少哪个“切片”) )。

完整代码位于:https://github.com/andrwo/react-redux-connectUUID/blob/master/Redux_UUID.tsx

所有这些都很好用。当我的React应用运行时,它将本地组件状态注册到uuid redux部分(并在该组件卸载时将其删除):

enter image description here

我现在的问题是,在我的connectUUID()HOC实现中,我在一些声明中使用了 any ,因此这删除了我的组件类型检查,如果您使用react-redux中的connect()HOC:

  • lib / Redux_UUID.tsx [connect_UUID库]
export const connectUUID = (name:string, mapStateToProps?:any) => <T extends Matching<{}, T>>(Component:React.ComponentType<T>) => {
  const ConnectedComponent = connect(
    (mapStateToProps?wrapMapStateToProps(mapStateToProps, name):null)
  )(Component);
  class ConnectUUID extends React.Component<any> {
    uuid:string='';
    dispatchUUID = (action:any) => {
      const action2={
        ...action,
        meta: Object.assign(
            {},
            action.meta,
            name && {[NAME_KEY]: name},
            this.uuid && {[UUID_KEY]: this.uuid},
        )
      }
      this.props.dispatch(action2);
    }
    componentWillMount() {
      this.uuid = this.props.uuid || createUUID();

      if (!this.props.uuid) {
        this.props.dispatch({
          type: REGISTER,
          meta: {
            [UUID_KEY]: this.uuid,
            [NAME_KEY]: name
          }
        });
      }
    }
    componentWillUnmount() {
      if (!this.props.uuid) {
        this.props.dispatch({
          type: UNREGISTER,
          meta: {
            [UUID_KEY]: this.uuid,
            [NAME_KEY]: name
          }
      });
    }}
    render() {
      return (
        <ConnectedComponent
          {...this.props}
          dispatchUUID={this.dispatchUUID}
          uuid={this.uuid}
        />
      );
    }
  }
  return connect()(ConnectUUID);
};

所以现在当我使用此组件时,它可以工作,因为我使用React.Component(any)消除了类型错误,我还在mapStateToProps中使用了(any)...但是...我丢失了该组件VS代码中的prop类型检查(以下代码会触发TS错误,因为invalidProp无效,因此仅允许props(userClickPaths,company_id,uuid?):

  • test.tsx [使用AdminUserListContainer的组件]
import AdminUserListContainer from 'component/svc/AdminUserListContainer';
...
(props) => return (
...
   <AdminUserListContainer
              userClickPaths={`${parentPath}/AdminUser`} 
              company_id={company_id}
              invalidProp={'blahBlah'}  // this prop should be invalid
              />

我试图查看react-redux的类型以了解它们的工作方式,但是所有的InferableProps等都让它感到困惑。这看起来非常密集!

任何大师都可以向我指出正确的方向,我该如何进行connectUUID()函数的键入,以便正确进行键入?预先感谢!

0 个答案:

没有答案