Wonderjar's Blog

React Typescript踩坑记录

2018-06-21

引入React

使用
import React from ‘react’;
报错
/node_modules/@types/react/index”‘ has no default export.
解决办法
import * as React from ‘react’;

引入PropTypes

import { PropTypes } from ‘react’;
解决办法
With React 15.5, importing PropTypes from React is deprecated in favour of importing from the new ‘prop-types’ package.
Reference
https://github.com/react-toolbox/react-toolbox/issues/1410

React-router-dom注入

当使用withRouter(MyComponent)时
Argument of type ‘typeof AppMenu’ is not assignable to parameter of type ‘ComponentType<RouteComponentProps<any, StaticContext>>’.
或者是在component里使用react-router-dom注入的属性,比如history
Property ‘history’ does not exist on type ‘Readonly<{ children?: ReactNode; }> & Readonly<{}>’.
解决办法
import { withRouter, RouteComponentProps } from ‘react-router-dom’
class MyComponent extends React.Component<RouteComponentProps<{}>, any> { … }
export default withRouter(MyComponent)

require.context

错误
Property ‘context’ does not exist on type ‘NodeRequire’.
解决办法
yarn add @types/webpack-env

使用State出错

错误
Property ‘somePropInState’ does not exist on type ‘Readonly<{}>’.
原因
我的component,一开始是这样使用generics
class MyComp extends React.Component<IComponentProps & IStateProps & RouteComponentProps & IDispatchThunkProp>
export default withRouter(connect(mapStateToProps)(MyComp))
看了React.Component的types定义,
class Component<P, S> {
constructor(props: P, context?: any);

setState<K extends keyof S>(
    state: ((prevState: Readonly<S>, props: P) => (Pick<S, K> | S | null)) | (Pick<S, K> | S | null),
    callback?: () => void
): void;

...

}
所以一定是第二个泛型,才是state的类型定义,所以要改成,
class MyComp extends React.Component<IComponentProps & RouteComponentProps & IDispatchThunkProp, IStateProps> {
public constructor(props: IComponentProps & RouteComponentProps & IDispatchThunkProp) {
super(props)
this.state = {
somePropInState: ‘test’
}
}
}

使用window下的全局变量

解决办法
interface IWindow extends Window {
SompProp: any
}
declare var window: IWindow;

引入Less但是是empty object

import styles from ‘./index.less’;
发现styles是{}
解决办法,关键是modules: true,我这样改过就工作了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
test: /\.less$/,
loaders: [
{
loader: require.resolve('style-loader'),
options: {
modules: true
}
},
{
loader: require.resolve('css-loader'),
options: {
modules: true
}
},
{
loader: require.resolve('sass-loader'),
options: {
modules: true
}
}
]
},

Decorator编译错误,syntax error

这个和下一个问题其实不是typescirpt的问题,但也记一下
解决办法,.babelrl文件,添加插件
{
“presets”: [
[ “es2015”, { “modules”: false } ],
“stage-0”,
“react”
],
“plugins”: [
“transform-class-properties”,
“transform-decorators-legacy”
]
}

Less中函数报错

Inline JavaScript is not enabled. Is it set in your options?
参考 https://github.com/ant-design/ant-motion/issues/44
关键是要这个属性 javascriptEnabled: true
看起来这个属性对于sass-loader没用,后来换成less-loader来加载less
{
loader: require.resolve(‘less-loader’),
options: {
modules: true,
javascriptEnabled: true
}
}