1. 安装
- create-react-app
- 直接 create-react-app 项目名 —typescript 即可(等同于下面两步操作)
```javascript
// 1. To start a new Create React App project with TypeScript, you can run:
npx create-react-app my-app —template typescript
or
yarn create react-app my-app —template typescript
// 2. To add TypeScript to a Create React App project, first install it: npm install —save typescript @types/node @types/react @types/react-dom @types/jest
or
yarn add typescript @types/node @types/react @types/react-dom @types/jest
<a name="d6ppt"></a>
## 2. State 和 Props
<a name="WjD1L"></a>
### 2.1 Class组件写法
- **Component<IProps, IState> 若该组件没有定义IProps,传{} 空对象即可**
- **Component<{}, IState>**
**App.tsx**
```javascript
import React from 'react';
import Hello from './components/Hello';
function App() {
return (
<div className="App">
<Hello title="标题" age={20} />
</div>
);
}
export default App;
components/Hello.tsx
import React, { Component } from 'react';
// 通过接口声明props
interface IProps {
title: string;
age?: number;
}
// 通过接口声明state
interface IState {
count: number;
}
export default class Hello extends Component<IProps, IState> {
// 实现state
public readonly state: Readonly<IState> = {
count: 1000,
};
public handleChange = () => {
this.setState({ count: 2000 });
};
render() {
const { title, age } = this.props;
const { count } = this.state;
return (
<div>
<h2>
Hello {title} - age: {age}
<div>
<h3>{count}</h3>
<button onClick={this.handleChange}>按钮</button>
</div>
</h2>
</div>
);
}
}
2.2 Functional组件写法
- 如果IProps里有对象属性,可以再声明个接口描述这个对象
- 函数组件里**React.FC
这里不需要传IState,因为函数组件里是使用hooks的**
App.tsx
import React from 'react';
import { TextFiled } from './components/TextFiled';
function App() {
return (
<div className="App">
<TextFiled
text="Hello"
person={{ firstName: 'Chenxii', lastName: 'C' }}
/>
</div>
);
}
export default App;
components/TextField.tsx
import React from 'react';
interface IPerson {
firstName: string;
lastName: string;
}
interface IProps {
text: string;
ok?: boolean;
index?: number;
fn?: (bob: string) => void;
person?: IPerson;
// obj: {
// f1: string
// }
}
export const TextFiled: React.FC<IProps> = (props) => {
return <div>{props.text}</div>;
};
3. Hooks
3.1 useState Hook
export const TextFiled: React.FC<IProps> = (props) => {
const [count, setCount] = useState<number | null>(5);
setCount(null);
return <div>{props.text}</div>;
};
interface TextNode {
text: string
}
export const TextFiled: React.FC<IProps> = (props) => {
const [count, setCount] = useState<TextNode>({text: "hello"});
return <div>{props.text}</div>;
};
3.2 useRef Hook + 事件
App.tsx
import React from 'react';
import { TextFiled } from './components/TextField';
function App() {
return (
<div className="App">
<TextFiled
text="Hello"
person={{ firstName: 'Chenxii', lastName: 'C' }}
handleChange={e => {....}}
/>
</div>
);
}
export default App;
components/TextField.tsx
import React, { useState, useRef } from 'react';
interface IPerson {
firstName: string;
lastName: string;
}
interface IProps {
text: string;
ok?: boolean;
index?: number;
fn?: (bob: string) => void;
person?: IPerson;
handleChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
}
export const TextFiled: React.FC<IProps> = (props) => {
const inputRef = useRef<HTMLInputElement>(null);
const divRef = useRef<HTMLDivElement>(null);
return (
<div ref={divRef}>
<input ref={inputRef} onChange={props.handleChange} />
</div>
);
};
3.3 useReducer Hook
import React, { useReducer } from 'react';
type Actions = { type: 'add'; text: string } | { type: 'remove'; idx: number };
interface Todo {
text: string;
complete: boolean;
}
type State = Todo[];
const TodoReducer = (state: State, action: Actions) => {
switch (action.type) {
case 'add':
return [...state, { text: action.text, complete: false }];
case 'remove':
return state.filter((_, i) => action.idx !== i);
default:
return state;
}
};
export const ReducerExample: React.FC = () => {
const [todos, dispatch] = useReducer(TodoReducer, []);
return (
<div>
{JSON.stringify(todos)}
<button
onClick={() => {
dispatch({ type: 'add', text: '...' });
}}
>
+
</button>
</div>
);
};
4. 事件处理
- 子组件的IProps接口中这样定义方法: onMyClick: (data: string) => void
App.tsx
import React from 'react';
import Hello from './components/Hello';
function App() {
const handleClick = (data: string) => {
console.log(data);
};
return (
<div className="App">
<Hello title="标题" age={20} onMyClick={handleClick} />
</div>
);
}
export default App;
components/Hello.tsx
import React, { Component } from 'react';
interface IProps {
title: string;
age?: number;
onMyClick: (data: string) => void;
}
// 通过接口声明state
interface IState {
count: number;
}
export default class Hello extends Component<IProps, IState> {
// 实现state
public readonly state: Readonly<IState> = {
count: 1000,
};
public handleChange = () => {
this.setState({ count: 2000 });
};
public handleSendMsg = () => {
this.props.onMyClick('child event');
};
render() {
const { title, age } = this.props;
const { count } = this.state;
return (
<div>
<h2>
Hello {title} - age: {age}
<div>
<h3>{count}</h3>
<button onClick={this.handleChange}>按钮</button>
<button onClick={this.handleSendMsg}>Send Msg</button>
</div>
</h2>
</div>
);
}
}