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

  1. <a name="d6ppt"></a>
  2. ## 2. State 和 Props
  3. <a name="WjD1L"></a>
  4. ### 2.1 Class组件写法
  5. - **Component<IProps, IState> 若该组件没有定义IProps,传{} 空对象即可**
  6. - **Component<{}, IState>**
  7. **App.tsx**
  8. ```javascript
  9. import React from 'react';
  10. import Hello from './components/Hello';
  11. function App() {
  12. return (
  13. <div className="App">
  14. <Hello title="标题" age={20} />
  15. </div>
  16. );
  17. }
  18. export default App;

components/Hello.tsx

  1. import React, { Component } from 'react';
  2. // 通过接口声明props
  3. interface IProps {
  4. title: string;
  5. age?: number;
  6. }
  7. // 通过接口声明state
  8. interface IState {
  9. count: number;
  10. }
  11. export default class Hello extends Component<IProps, IState> {
  12. // 实现state
  13. public readonly state: Readonly<IState> = {
  14. count: 1000,
  15. };
  16. public handleChange = () => {
  17. this.setState({ count: 2000 });
  18. };
  19. render() {
  20. const { title, age } = this.props;
  21. const { count } = this.state;
  22. return (
  23. <div>
  24. <h2>
  25. Hello {title} - age: {age}
  26. <div>
  27. <h3>{count}</h3>
  28. <button onClick={this.handleChange}>按钮</button>
  29. </div>
  30. </h2>
  31. </div>
  32. );
  33. }
  34. }

2.2 Functional组件写法

  • 如果IProps里有对象属性,可以再声明个接口描述这个对象
  • 函数组件里**React.FC这里不需要传IState,因为函数组件里是使用hooks的**

App.tsx

  1. import React from 'react';
  2. import { TextFiled } from './components/TextFiled';
  3. function App() {
  4. return (
  5. <div className="App">
  6. <TextFiled
  7. text="Hello"
  8. person={{ firstName: 'Chenxii', lastName: 'C' }}
  9. />
  10. </div>
  11. );
  12. }
  13. export default App;

components/TextField.tsx

  1. import React from 'react';
  2. interface IPerson {
  3. firstName: string;
  4. lastName: string;
  5. }
  6. interface IProps {
  7. text: string;
  8. ok?: boolean;
  9. index?: number;
  10. fn?: (bob: string) => void;
  11. person?: IPerson;
  12. // obj: {
  13. // f1: string
  14. // }
  15. }
  16. export const TextFiled: React.FC<IProps> = (props) => {
  17. return <div>{props.text}</div>;
  18. };

3. Hooks

3.1 useState Hook

  1. export const TextFiled: React.FC<IProps> = (props) => {
  2. const [count, setCount] = useState<number | null>(5);
  3. setCount(null);
  4. return <div>{props.text}</div>;
  5. };
  1. interface TextNode {
  2. text: string
  3. }
  4. export const TextFiled: React.FC<IProps> = (props) => {
  5. const [count, setCount] = useState<TextNode>({text: "hello"});
  6. return <div>{props.text}</div>;
  7. };

3.2 useRef Hook + 事件

App.tsx

  1. import React from 'react';
  2. import { TextFiled } from './components/TextField';
  3. function App() {
  4. return (
  5. <div className="App">
  6. <TextFiled
  7. text="Hello"
  8. person={{ firstName: 'Chenxii', lastName: 'C' }}
  9. handleChange={e => {....}}
  10. />
  11. </div>
  12. );
  13. }
  14. export default App;

components/TextField.tsx

  1. import React, { useState, useRef } from 'react';
  2. interface IPerson {
  3. firstName: string;
  4. lastName: string;
  5. }
  6. interface IProps {
  7. text: string;
  8. ok?: boolean;
  9. index?: number;
  10. fn?: (bob: string) => void;
  11. person?: IPerson;
  12. handleChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
  13. }
  14. export const TextFiled: React.FC<IProps> = (props) => {
  15. const inputRef = useRef<HTMLInputElement>(null);
  16. const divRef = useRef<HTMLDivElement>(null);
  17. return (
  18. <div ref={divRef}>
  19. <input ref={inputRef} onChange={props.handleChange} />
  20. </div>
  21. );
  22. };

3.3 useReducer Hook

  1. import React, { useReducer } from 'react';
  2. type Actions = { type: 'add'; text: string } | { type: 'remove'; idx: number };
  3. interface Todo {
  4. text: string;
  5. complete: boolean;
  6. }
  7. type State = Todo[];
  8. const TodoReducer = (state: State, action: Actions) => {
  9. switch (action.type) {
  10. case 'add':
  11. return [...state, { text: action.text, complete: false }];
  12. case 'remove':
  13. return state.filter((_, i) => action.idx !== i);
  14. default:
  15. return state;
  16. }
  17. };
  18. export const ReducerExample: React.FC = () => {
  19. const [todos, dispatch] = useReducer(TodoReducer, []);
  20. return (
  21. <div>
  22. {JSON.stringify(todos)}
  23. <button
  24. onClick={() => {
  25. dispatch({ type: 'add', text: '...' });
  26. }}
  27. >
  28. +
  29. </button>
  30. </div>
  31. );
  32. };

4. 事件处理

  • 子组件的IProps接口中这样定义方法: onMyClick: (data: string) => void

App.tsx

  1. import React from 'react';
  2. import Hello from './components/Hello';
  3. function App() {
  4. const handleClick = (data: string) => {
  5. console.log(data);
  6. };
  7. return (
  8. <div className="App">
  9. <Hello title="标题" age={20} onMyClick={handleClick} />
  10. </div>
  11. );
  12. }
  13. export default App;

components/Hello.tsx

  1. import React, { Component } from 'react';
  2. interface IProps {
  3. title: string;
  4. age?: number;
  5. onMyClick: (data: string) => void;
  6. }
  7. // 通过接口声明state
  8. interface IState {
  9. count: number;
  10. }
  11. export default class Hello extends Component<IProps, IState> {
  12. // 实现state
  13. public readonly state: Readonly<IState> = {
  14. count: 1000,
  15. };
  16. public handleChange = () => {
  17. this.setState({ count: 2000 });
  18. };
  19. public handleSendMsg = () => {
  20. this.props.onMyClick('child event');
  21. };
  22. render() {
  23. const { title, age } = this.props;
  24. const { count } = this.state;
  25. return (
  26. <div>
  27. <h2>
  28. Hello {title} - age: {age}
  29. <div>
  30. <h3>{count}</h3>
  31. <button onClick={this.handleChange}>按钮</button>
  32. <button onClick={this.handleSendMsg}>Send Msg</button>
  33. </div>
  34. </h2>
  35. </div>
  36. );
  37. }
  38. }