Javascript

React+typescrip项目实战:从零开始的React与TypeScript入门教程

本文主要是介绍React+typescrip项目实战:从零开始的React与TypeScript入门教程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

本文详细介绍了如何在React项目中使用TypeScript,包括初始化项目、配置TypeScript环境、开发基本组件以及状态管理等关键步骤,帮助开发者掌握React+TypeScript项目全流程。

React与TypeScript简介
React框架简介

React 是一个由 Facebook 开发并维护的 JavaScript 库,用于构建用户界面。它主要用来构建单页面应用,通过将界面分解为多个可重用的组件来管理大量数据和复杂交互。React 的核心特点包括虚拟 DOM、单向数据流和 JSX 语法。React 的高效渲染机制使其成为构建高性能应用的理想选择。

TypeScript语言简介

TypeScript 是由微软开发的一种静态类型语言,它是 JavaScript 的超集。类型系统可以帮助开发者在编码过程中检测潜在错误,提高代码的可维护性和可读性。TypeScript 支持接口、类、泛型等现代编程语言特性,使得代码结构更加清晰和易于管理。TypeScript 编译后输出的是标准的 JavaScript 代码,可以在任何支持 JavaScript 的环境中运行。

React项目中使用TypeScript的好处

在 React 项目中使用 TypeScript 可以带来以下好处:

  1. 类型检查:在编写代码时,TypeScript 提供了静态类型检查,能帮助开发者在编译阶段发现错误。
  2. 更好的工具支持:IDE(如 VS Code)可以利用 TypeScript 的类型信息提供更好的代码补全、导航和重构支持。
  3. 清晰的API文档:通过类型声明,可以清晰地了解组件的输入输出,便于团队成员之间的沟通和协作。
  4. 可维护性:类型信息使得代码更加清晰易读,便于后续维护和升级。
  5. 更好的集成:TypeScript 支持与各种库和框架的无缝集成,例如 Redux, React Router 等,可以直接使用类型定义文件(.d.ts)。
创建React+TypeScript项目
使用Create React App初始化项目

Create React App 是一个命令行工具,可以帮助你快速创建和配置一个新的 React 项目。它预先配置了热重载、代码分离、错误通知和环境变量等特性。以下是使用 Create React App 初始化一个新的 React + TypeScript 项目的步骤:

  1. 安装 Node.js 和 npm。
  2. 全局安装 Create React App:
npm install -g create-react-app
  1. 使用 Create React App 创建新的 TypeScript 项目:
npx create-react-app my-app --template typescript
配置TypeScript环境

在创建项目后,项目中已经有了基础的 TypeScript 配置文件 tsconfig.json。如果需要进行额外的配置,可以在 tsconfig.json 文件中进行修改。例如,可以添加或修改以下属性:

{
  "compilerOptions": {
    "target": "es6",
    "module": "esnext",
    "strict": true,
    "jsx": "react",
    "baseUrl": "src",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src"]
}
配置VS Code等IDE支持

为了使 VS Code 为 TypeScript 项目提供更好的支持,可以安装 TypeScript 插件,如 TypeScript and JavaScript (ES6) Code LintTypeScript Hero。此外,确保在 VS Code 中安装了 TypeScripttslint 插件,并将其配置文件 .editorconfig.vscode/settings.json 放入项目中。例如,可以添加以下配置:

{
  "editor.tabSize": 2,
  "editor.insertSpaces": true,
  "editor.formatOnSave": true,
  "javascript.updateImportsOnFileMove.enabled": "always",
  "typescript.updateImportsOnFileMove.enabled": "always",
  "javascript.validate.addMissingImports": true,
  "typescript.validate.addMissingImports": true
}
基本组件开发
函数组件与类组件的TypeScript实现

函数组件

函数组件是 React 中最简单的组件类型,它接收 props 作为输入并返回 JSX。以下是一个简单的函数组件示例:

import React from 'react';

type Props = {
  name: string;
};

const Greeting: React.FC<Props> = (props) => {
  return <h1>Hello, {props.name}</h1>;
};

export default Greeting;

类组件

类组件可以包含复杂的逻辑,如生命周期方法。以下是一个包含 state 的类组件示例:

import React, { Component } from 'react';

interface Props {
  message: string;
}

interface State {
  count: number;
}

class Counter extends Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = { count: 0 };
  }

  incrementCount = () => {
    this.setState((prevState) => ({ count: prevState.count + 1 }));
  };

  render() {
    return (
      <div>
        <h1>{this.props.message}</h1>
        <p>Count: {this.state.count}</p>
        <button onClick={this.incrementCount}>Increment</button>
      </div>
    );
  }
}

export default Counter;
使用Props和State

Props

Props 是组件之间的通信方式之一,用于从父组件向子组件传递数据。以下是使用函数组件和 Props 的示例:

interface GreetingProps {
  name: string;
}

const Greeting: React.FC<GreetingProps> = (props) => {
  return <h1>Hello, {props.name}</h1>;
};

export default Greeting;

State

State 是组件内部的状态,用于管理组件的内部数据。以下是使用类组件和 State 的示例:

import React, { Component } from 'react';

interface CounterProps {
  message: string;
}

interface CounterState {
  count: number;
}

class Counter extends Component<CounterProps, CounterState> {
  constructor(props: CounterProps) {
    super(props);
    this.state = { count: 0 };
  }

  incrementCount = () => {
    this.setState((prevState) => ({ count: prevState.count + 1 }));
  };

  render() {
    return (
      <div>
        <h1>{this.props.message}</h1>
        <p>Count: {this.state.count}</p>
        <button onClick={this.incrementCount}>Increment</button>
      </div>
    );
  }
}

export default Counter;
常见组件模式

高阶组件

高阶组件是一种设计模式,用于封装组件逻辑。以下是一个简单的高阶组件示例:

import React from 'react';

interface HOCProps {
  name: string;
}

const withGreeting = <P extends object>(Component: React.ComponentType<P>) => {
  const GreetingHOC: React.FC<P & HOCProps> = (props) => {
    return <Component {...props} />;
  };

  return GreetingHOC;
};

const Greeting: React.FC<HOCProps> = (props) => {
  return <h1>Hello, {props.name}</h1>;
};

const EnhancedGreeting = withGreeting(Greeting);

export default EnhancedGreeting;

Render Props

Render Props 是一种模式,用于在组件之间传递函数。以下是一个简单的 Render Props 示例:

import React from 'react';

interface Props {
  name: string;
  render: (name: string) => React.ReactNode;
}

const Greeting: React.FC<Props> = (props) => {
  return props.render(props.name);
};

export default Greeting;

使用 Render Props 的组件示例:

import React from 'react';
import Greeting from './Greeting';

const App: React.FC = () => {
  return (
    <Greeting name="World">
      {(name) => <h1>Hello, {name}</h1>}
    </Greeting>
  );
};

export default App;
状态管理和生命周期
使用React Hooks管理状态

React Hooks 是 React 16.8 版本引入的新特性,允许在不编写类的情况下使用状态和其他 React 特性。以下是使用 useStateuseEffect 的示例:

useState

useState 用于在函数组件中添加状态。

import React, { useState } from 'react';

const Counter: React.FC = () => {
  const [count, setCount] = useState(0);

  const incrementCount = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={incrementCount}>Increment</button>
    </div>
  );
};

export default Counter;

useEffect

useEffect 用于执行副作用操作,例如数据获取、订阅或手动 DOM 操作。

import React, { useState, useEffect } from 'react';

const Counter: React.FC = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log('Component rendered');
    document.title = `You clicked ${count} times`;
  }, [count]);

  const incrementCount = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={incrementCount}>Increment</button>
    </div>
  );
};

export default Counter;
生命周期钩子在TypeScript中的应用

在类组件中,生命周期钩子允许你控制组件的生命周期。虽然 React Hooks 使得生命周期管理变得更加简单,但理解生命周期钩子仍然很重要。

componentDidMount

componentDidMount 是在组件首次渲染后立即调用的钩子。以下是一个使用 componentDidMount 的示例:

import React, { Component } from 'react';

interface Props {
  message: string;
}

interface State {
  data: string;
}

class App extends Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = { data: '' };
  }

  componentDidMount() {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => this.setState({ data }));
  }

  render() {
    return (
      <div>
        <h1>{this.props.message}</h1>
        <p>Data: {this.state.data}</p>
      </div>
    );
  }
}

export default App;

componentDidUpdate

componentDidUpdate 在组件更新后调用,可以用于执行副作用操作。

import React, { Component } from 'react';

interface Props {
  message: string;
}

interface State {
  data: string;
}

class App extends Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = { data: '' };
  }

  componentDidMount() {
    this.fetchData();
  }

  componentDidUpdate(prevProps: Props, prevState: State) {
    if (prevState.data !== this.state.data) {
      // Perform side effects
    }
  }

  fetchData = () => {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => this.setState({ data }));
  };

  render() {
    return (
      <div>
        <h1>{this.props.message}</h1>
        <p>Data: {this.state.data}</p>
      </div>
    );
  }
}

export default App;
Context API与Redux简介

Context API

Context API 用于在组件树中传递数据,避免在每个组件中进行 props 传递。以下是一个简单的 Context API 示例:

import React, { createContext, useContext, useState } from 'react';

const ThemeContext = createContext('light');

const ThemeProvider: React.FC = ({ children }) => {
  const [theme, setTheme] = useState('light');

  const toggleTheme = () => {
    setTheme(theme === 'light' ? 'dark' : 'light');
  };

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
};

const useTheme = () => useContext(ThemeContext);

const App: React.FC = () => {
  const { theme, toggleTheme } = useTheme();

  return (
    <ThemeProvider>
      <div>
        <h1>Theme: {theme}</h1>
        <button onClick={toggleTheme}>Toggle Theme</button>
      </div>
    </ThemeProvider>
  );
};

export default App;

Redux

Redux 是一个用于管理应用状态的库,它提供了一个单一的可预测的状态树。以下是使用 Redux 的基本步骤:

  1. 安装 Redux:
npm install redux
  1. 创建 Redux store:
import { createStore } from 'redux';

interface AppState {
  count: number;
}

const initialState: AppState = { count: 0 };

const rootReducer = (state = initialState, action: any) => {
  switch (action.type) {
    case 'increment':
      return { ...state, count: state.count + 1 };
    default:
      return state;
  }
};

const store = createStore(rootReducer);

export default store;
  1. 使用 Provider 组件在应用中提供 store:
import React from 'react';
import { Provider } from 'react-redux';
import store from './store';
import Counter from './Counter';

const App: React.FC = () => {
  return (
    <Provider store={store}>
      <Counter />
    </Provider>
  );
};

export default App;
  1. 在组件中使用 useSelectoruseDispatch
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';

interface Props {
  name: string;
}

const Counter: React.FC<Props> = (props) => {
  const count = useSelector((state: AppState) => state.count);
  const dispatch = useDispatch();

  useEffect(() => {
    console.log('Count:', count);
  }, [count]);

  const incrementCount = () => {
    dispatch({ type: 'increment' });
  };

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={incrementCount}>Increment</button>
    </div>
  );
};

export default Counter;
路由与导航
使用React Router实现页面导航

React Router 是一个用于实现客户端路由的库,支持将不同路径映射到不同的组件。以下是使用 React Router 的基本步骤:

  1. 安装 React Router:
npm install react-router-dom
  1. 创建路由配置:
import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';
import Home from './Home';
import About from './About';

const App: React.FC = () => {
  return (
    <Router>
      <div>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about">About</Link>
          </li>
        </ul>

        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/about" component={About} />
        </Switch>
      </div>
    </Router>
  );
};

export default App;
  1. 创建对应的组件:
import React from 'react';

const Home: React.FC = () => <h2>Home</h2>;

export default Home;
import React from 'react';

const About: React.FC = () => <h2>About</h2>;

export default About;
定义路由和页面组件

通过 Route 组件定义不同路径的页面组件。以下是定义多个路由的示例:

import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';
import Home from './Home';
import About from './About';
import Contact from './Contact';

const App: React.FC = () => {
  return (
    <Router>
      <div>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about">About</Link>
          </li>
          <li>
            <Link to="/contact">Contact</Link>
          </li>
        </ul>

        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/about" component={About} />
          <Route path="/contact" component={Contact} />
        </Switch>
      </div>
    </Router>
  );
};

export default App;
路由参数与查询参数

路由参数

通过在路径中定义参数,可以在路由组件中访问参数值。以下是使用路由参数的示例:

import React from 'react';
import { Router, Route, Switch, Link, useParams } from 'react-router-dom';

const App: React.FC = () => {
  return (
    <Router>
      <ul>
        <li>
          <Link to="/users/1">User 1</Link>
        </li>
        <li>
          <Link to="/users/2">User 2</Link>
        </li>
      </ul>

      <Switch>
        <Route path="/users/:userId" component={User} />
      </Switch>
    </Router>
  );
};

const User: React.FC = () => {
  const { userId } = useParams<Record<string, string>>();

  return (
    <div>
      <h2>User {userId}</h2>
    </div>
  );
};

export default App;

查询参数

通过在路径中定义查询参数,可以在路由组件中访问查询参数值。以下是使用查询参数的示例:

import React from 'react';
import { Router, Route, Switch, Link, useLocation } from 'react-router-dom';

const App: React.FC = () => {
  return (
    <Router>
      <ul>
        <li>
          <Link to="/search?q=react">Search React</Link>
        </li>
        <li>
          <Link to="/search?q=typescript">Search TypeScript</Link>
        </li>
      </ul>

      <Switch>
        <Route path="/search" component={Search} />
      </Switch>
    </Router>
  );
};

const Search: React.FC = () => {
  const location = useLocation();
  const { q } = new URLSearchParams(location.search);

  return (
    <div>
      <h2>Search results for: {q}</h2>
    </div>
  );
};

export default App;
项目实战案例
搭建一个简单的待办事项应用

待办事项应用是一个经典的示例,用于展示 React 和 TypeScript 的基本功能。以下是构建待办事项应用的步骤:

  1. 使用 Create React App 创建一个新的项目:
npx create-react-app todo-app --template typescript
  1. src 目录下创建以下文件:

    • App.tsx:主组件
    • TodoList.tsx:待办事项列表组件
    • TodoItem.tsx:单个待办事项组件
    • TodoForm.tsx:待办事项表单组件
  2. App.tsx 中,定义主组件:
import React, { useState } from 'react';
import TodoList from './TodoList';
import TodoForm from './TodoForm';

interface Todo {
  id: number;
  text: string;
  completed: boolean;
}

const App: React.FC = () => {
  const [todos, setTodos] = useState<Todo[]>([]);

  const addTodo = (text: string) => {
    const newTodo: Todo = {
      id: Date.now(),
      text,
      completed: false,
    };
    setTodos([...todos, newTodo]);
  };

  const toggleTodo = (id: number) => {
    const updatedTodos = todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    );
    setTodos(updatedTodos);
  };

  const deleteTodo = (id: number) => {
    const remainingTodos = todos.filter(todo => todo.id !== id);
    setTodos(remainingTodos);
  };

  return (
    <div>
      <h1>Todo List</h1>
      <TodoForm addTodo={addTodo} />
      <TodoList todos={todos} toggleTodo={toggleTodo} deleteTodo={deleteTodo} />
    </div>
  );
};

export default App;
  1. TodoList.tsx 中,定义待办事项列表组件:
import React from 'react';
import TodoItem from './TodoItem';

interface TodoListProps {
  todos: Todo[];
  toggleTodo: (id: number) => void;
  deleteTodo: (id: number) => void;
}

const TodoList: React.FC<TodoListProps> = ({ todos, toggleTodo, deleteTodo }) => {
  return (
    <ul>
      {todos.map(todo => (
        <TodoItem key={todo.id} todo={todo} toggleTodo={toggleTodo} deleteTodo={deleteTodo} />
      ))}
    </ul>
  );
};

export default TodoList;
  1. TodoItem.tsx 中,定义单个待办事项组件:
import React from 'react';

interface TodoItemProps {
  todo: Todo;
  toggleTodo: (id: number) => void;
  deleteTodo: (id: number) => void;
}

const TodoItem: React.FC<TodoItemProps> = ({ todo, toggleTodo, deleteTodo }) => {
  return (
    <li>
      <span style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>
        {todo.text}
      </span>
      <button onClick={() => toggleTodo(todo.id)}>Toggle</button>
      <button onClick={() => deleteTodo(todo.id)}>Delete</button>
    </li>
  );
};

export default TodoItem;
  1. TodoForm.tsx 中,定义待办事项表单组件:
import React, { useState } from 'react';

interface TodoFormProps {
  addTodo: (text: string) => void;
}

const TodoForm: React.FC<TodoFormProps> = ({ addTodo }) => {
  const [text, setText] = useState('');

  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    addTodo(text);
    setText('');
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Add a new todo"
        required
      />
      <button type="submit">Add</button>
    </form>
  );
};

export default TodoForm;
功能介绍与实现
  • 添加待办事项:用户可以在表单中输入待办事项,并通过点击“添加”按钮将其添加到列表中。
  • 标记待办事项为已完成:用户可以点击待办事项旁边的“完成”按钮将其标记为已完成。
  • 删除待办事项:用户可以点击待办事项旁边的“删除”按钮将其从列表中删除。
项目代码结构与最佳实践

项目代码结构如下:

src/
├── App.tsx
├── index.tsx
├── TodoForm.tsx
├── TodoItem.tsx
└── TodoList.tsx

最佳实践

  • 使用 TypeScript 进行类型定义:在组件和函数中明确定义类型,以提高代码的可读性和可维护性。
  • 组件职责单一:每个组件负责单一的功能,例如 TodoForm 负责添加待办事项,TodoItem 负责显示和操作单个待办事项。
  • 状态管理:使用 useStateuseEffect 管理组件状态和副作用。
  • 代码复用:通过高阶组件、渲染属性等方式提高代码复用性。

通过遵循这些最佳实践,可以构建出结构清晰、易于维护的 React + TypeScript 项目。

这篇关于React+typescrip项目实战:从零开始的React与TypeScript入门教程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!