Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

react + next.js + typescript配置 #2

Open
Feniast opened this issue May 13, 2020 · 0 comments
Open

react + next.js + typescript配置 #2

Feniast opened this issue May 13, 2020 · 0 comments

Comments

@Feniast
Copy link
Owner

Feniast commented May 13, 2020

react + next.js + typescript配置

由于之前对typescript不熟悉,所以记录一下流程

  1. 安装typescript和types依赖
yarn add typescript
yarn add @types/react @types/react-dom
  1. 在项目根目录下创建tsconfig.json
touch tsconfig.json
  1. 启动服务
yarn dev # 此处是样例,输入你的启动服务命令

nexts.js会自动配置tsconfig.json并创建一个next-env.d.ts文件

  1. tsconfig.json路径别名配置

example:

 "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  }

paths下的路径都是以baseUrl为基础解析,所以@/开头的路径都会到src目录下去解析。baseUrl必须配置。

  1. styled-components配置

先安装依赖

yarn add @types/styled-components

声明主题文件, 按照自己的theme对象包含的属性修改。e.g.:

// import original module declarations
import 'styled-components'

// and extend them!
declare module 'styled-components' {
  export interface DefaultTheme {
    borderRadius: string

    colors: {
      main: string
      secondary: string
    }
  }
}
  1. class定义

所有class的属性必须声明在类代码块中, 根据需要选择修饰符private or public

e.g.

interface AInitOptions = {
    a?: string;
    b?: number;
}
class A {
    private a: string;
    public b: number;
    constructor(options: AInitOptions) {
        this.a = options.a;
        this.b = options.b;
    }
    
    //......
}
  1. redux create store

参考: https://stackoverflow.com/questions/50451854/trouble-with-typescript-typing-for-store-enhancers-in-redux-4-0

const composeEnhancers: <StoreExt, StateExt>(
  ...funcs: Array<StoreEnhancer<StoreExt>>
) => StoreEnhancer<StoreExt> =
  process.env.NODE_ENV !== 'production' ? composeWithDevTools : compose;

const myReducerEnhancer: StoreEnhancer = (
  createStore: StoreEnhancerStoreCreator
): StoreEnhancerStoreCreator => <S = any, A extends Action = AnyAction>(
  reducer: Reducer<S, A>,
  initialState: PreloadedState<S>
) => {
  // do something
  return createStore(reducer, initialState);
};

export default function configureStore(initialState: any) {
  const middlewares = [thunkMiddleware];
  const middlewareEnhancer = applyMiddleware(...middlewares);

  const enhancers: StoreEnhancer[] = [middlewareEnhancer];
  if (process.env.NODE_ENV === 'development') {
    enhancers.unshift(myReducerEnhancer);
  }

  const composedEnhancers = composeEnhancers(...enhancers);

  return createStore(rootReducer, initialState, composedEnhancers);
}
  1. Next.js Page 组件

https://stackoverflow.com/a/57441122

import { NextPage, NextPageContext } from 'next';

const MyComponent: NextPage<MyPropsInterface> = props => (
  // ...
)

interface Context extends NextPageContext {
  // any modifications to the default context, e.g. query types
}

MyComponent.getInitialProps = async (ctx: Context) => {
  // ...
  return props
}
  1. react组件文件名必须以tsx结尾

否则可能会报'SomeComponent' refers to a value, but is being used as a type here.

  1. tsx文件函数泛型报错问题

microsoft/TypeScript#15713 (comment)
在泛型后面加一个逗号

const f = <T,>(arg: T): T => {...}
  1. react-redux中useSelector hook的state参数类型获取不到
    https://stackoverflow.com/questions/57472105/react-redux-useselector-typescript-type-for-state
import {
  useSelector as useReduxSelector,
  TypedUseSelectorHook,
} from 'react-redux'

export type RootState = ReturnType<typeof rootRuducer>;

export const useSelector: TypedUseSelectorHook<RootState> = useReduxSelector;
  1. redux-thunk action定义

引入ThunkAction作为返回类型, 需要定义四个泛型类型<R, S, E, A>

R是最后ThunkAction的返回类型,S是State,E是ThunkAction额外参数(这里没有用到),A是ThunkDispatch即dispatch参数接受的action类型,可以是普通action也可以是ThunkAction。

export const someThunkAction = (...args: any[]): ThunkAction<
  void,
  RootState,
  unknown,
  Action<any>
> => (dispatch, getState) => {
  const { historyRoutes, backFlag, prevRoute } = getState().router;
  if (!backFlag) {
    if (historyRoutes[0] !== prevRoute) {
      const newHistoryRoutes = [prevRoute, ...historyRoutes];
      dispatch(setHistoryRoutes(newHistoryRoutes));
    }
  }
};
  1. React.forwardRef的Props类型需要带上children, 否则可能会报xxx is not assignable to type xxx
interface Props {
  // ......  
  children: React.ReactNode
}
  1. React组件定义

声明Props的定义

interface IProps {
  propA: number;
  propB: string;
  style: CSSProperties;
  // ……
}

函数式组件

const Comp: React.FC<IProps> = (props) => {
  <div>Hello</div>
};

Class组件

interface IState {
    stateA: number;
}
class Comp extends React.Component<IProps, IState> {
    constructor(props: IProps) {
        super(props);
        this.state = {
            stateA: 0
        };
    }
    
    // ……
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant