Umi(乌米) 中更好的使用connect

导读

你是否苦于在connect时和select时得不到提示呢?

又是怎样和page页面建立连接的呢?

正文

两个简单的Model

LoginModel.ts

export interface LoginModelState {
  title: string;
}
const state: LoginModelState = {
  title: '今天是劳动节!',
};
export default {
  state,
};

UserModel.ts

export interface UserModelState {
  name: string;
}
const state: UserModelState = {
  name: '小遁',
};
export default {
  state,
};

umi会自动识别models文件夹下的文件,models可以有多个,可以在不同的位置

page 目录下建一个ModelStateCollection.ts 文件

import { UserModelState, LoginModelState } from 'umi';

export default interface ModelStateCollection {
  LoginModel: LoginModelState;
  UserModel: UserModelState;
}

注意这行import { UserModelState, LoginModelState } from 'umi';,感觉umi可以做到把它们结合起来

namespace不指定则是文件的名字,需要是唯一的

使用select 就可以得到提示了

LoginModel.ts

import ModelStateCollection from '../ModelStateCollection';

export default {
  effects: {
    *loadPage({}: LoginModelState, { select }) {
      const name = yield select(
        ({ UserModel }: ModelStateCollection) => UserModel.name,
      );
    },
  },
};

在页面中的使用

不建议使用@connect,虽然属性已经通过mapStateToProps给组件了,但外面还是会提示没给到,还有其它tslint错误,而且...,两个字闹心!

Login.tsx

import React, { PureComponent } from 'react';
import { connect } from 'dva';
import ModelStateCollection from '../ModelStateCollection';
interface LoginProps {
  title: string;
}
const mapStateToProps = ({ LoginModel: { title } }: ModelStateCollection) => ({
  title,
});
class Login extends PureComponent<LoginProps> {
  public render() {
    const { title } = this.props;
    return <div>{title}</div>;
  }
}
export default connect(mapStateToProps)(Login);

结语

除了提示之外,还有约束,毕竟state要赋初值的,所以这里还是不好省去。

我之前一直觉得title这种重复的指定很麻烦,于是乎

interface LoginProps extends Partial<LoginModelState> {}

这样很是不好,或许以后TS能发展到很智能,但就目前来看:

  • Login 组件需要什么属性和connect 连接的属性是两回事
  • 值和类型定义也是两回事

最好的解决办法是少用 redux

宁可写无聊的代码,也不写耍聪明的代码 - React中文文档