React Tutorial
https://www.youtube.com/watch?v=SqcY0GlETPk
Vite
Vite (French word for "quick", pronounced /vit/, like "veet") is a new breed of frontend build tooling that significantly improves the frontend development experience.
File Structure
├── public/ # 静态资源目录
│ ├── favicon.ico # 网站图标
│ └── robots.txt # 搜索引擎爬虫配置文件
│
├── src/ # 源代码目录
│ ├── assets/ # 资源文件目录
│ │ ├── images/ # 图片资源
│ │ └── styles/ # 样式文件
│ │
│ ├── components/ # 可复用组件目录
│ │ ├── Button/
│ │ └── Header/
│ │
│ ├── hooks/ # 自定义 React Hooks
│ ├── layouts/ # 布局组件
│ ├── pages/ # 页面组件
│ ├── services/ # API 服务
│ ├── store/ # 状态管理(如 Redux)
│ ├── utils/ # 工具函数
│ ├── App.tsx # 应用根组件
│ ├── main.tsx # 应用入口文件
│ └── vite-env.d.ts # Vite 类型声明文件
│
├── .gitignore # Git 忽略文件配置
├── index.html # HTML 模板
├── package.json # 项目依赖配置
├── tsconfig.json # TypeScript 配置
├── vite.config.ts # Vite 配置文件
└── README.md # 项目说明文档
- `tsconfig.json`: telling TypeScript compiler how to compile code to javascript.
- `.tsx`: `ts` for TypeScript, `x` for react component.
- Using PascalCasing for react component, html tag is always lowercase.
public/
- 存放不需要经过打包的静态资源
- 可以通过绝对路径直接访问
src/assets/
- 存放需要经过打包处理的资源文件
- 包括图片、样式等
src/components/
- 存放可复用的 React 组件
- 每个组件通常包含自己的样式和测试文件
src/hooks/
- 存放自定义 React Hooks
- 用于提取可复用的状态逻辑
src/layouts/
- 存放页面布局组件
- 如页面框架、导航栏等
src/pages/
- 存放页面级组件
- 通常与路由配置对应
src/services/
- 存放 API 接口封装
- 处理与后端的数据交互
src/store/
- 状态管理相关文件
- 如 Redux、Zustand 等的配置和状态定义
src/utils/
- 存放工具函数
- 常用的辅助方法
配置文件
vite.config.ts:Vite 的配置文件tsconfig.json:TypeScript 配置package.json:项目依赖和脚本配置index.html:应用的 HTML 模板
入口文件
src/main.tsx:应用的入口文件src/App.tsx:根组件
建议
- 根据项目规模和需求适当调整目录结构
- 保持目录结构清晰,便于维护
- 可以添加
types/目录存放类型定义 - 可以添加
constants/目录存放常量 - 大型项目可以考虑按功能模块划分目录
Dom Render
- Virtual DOM is data structure and properties in javascript
- When the state changed, it will compare with the prev virtual DOM.
- Then update the actual DOM(This is done by react-dom package).
Demo
Create Vite with React demo project.
npm create vite@4.1.0
cd foo
npm i
npm run dev
Install Bootstrap
npm i bootstrap@5.2.3
CSS
index.css: global css, used byindex.js.app.css: component css, used byApp.jsand child components.
StrictMode
- It will send 2 requests after render to find potential problems
- Static check.
Prettier
Install code format plugin Prettier
cmd+shift+p => format document => configure default formatter
It can also format document by click right mouse.
Component
In function, it only can return one element.
function ListGroup() {
return (
// <h1>List</h1> error here
// its something like: React.createElement('h1')
<ul className="list-group">
<li className="list-group-item">An item</li>
</ul>
);
}
The solution is to wrap multi elements by div tags.
cmd+shit+p => wrap with abbreviation => div
Fragment
Use div wrap will add extra useless tag, use Fragment instead.
function ListGroup() {
return (
<Fragment>
<h1>List</h1>
<ul className="list-group">
<li className="list-group-item">An item</li>
</ul>
</Fragment>
);
}
Equivalent to <>
function ListGroup() {
return (
<>
<h1>List</h1>
<ul className="list-group">
<li className="list-group-item">An item</li>
</ul>
</>
);
}
Key Prop
Every child in a list should have a unique key prop. React needs it to track each item.
function ListGroup() {
const items = ["New York", "San Francisco", "Tokyo", "London", "Paris"];
return (
<div>
<h1>List</h1>
<ul className="list-group">
{items.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</div>
);
}
Chrome
Install React Developer Tools
https://react.dev/learn/react-developer-tools
Conditional Rendering
When use && in expression, if first args is true, the whole exp value will be the second arg.
function ListGroup() {
const items = [];
return (
<div>
<h1>List</h1>
{items.length === 0 && <p>No item found</p>}
<ul className="list-group">
{items.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</div>
);
}
Equivalent to
{items.length === 0 ? <p>No item found</p> : null}
function ListGroup() {
const items = [];
const message = items.length === 0 ? <p>No item found</p> : null
return (
<div>
<h1>List</h1>
{message}
<ul className="list-group">
{items.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</div>
);
}
Use Function
function ListGroup() {
const items = [];
const getMessage = () => {
return items.length === 0 ? <p>No item found</p> : null;
}
return (
<div>
<h1>List</h1>
{getMessage()}
<ul className="list-group">
{items.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</div>
);
}
Handle Events
OnClick Prop, index and event args is optional.
function ListGroup() {
const items = ["New York", "San Francisco", "Tokyo", "London", "Paris"];
return (
<div>
<h1>List</h1>
{items.length === 0 && <p>No item found</p>}
<ul className="list-group">
{items.map((item, index) => (
<li
className="list-group-item"
key={item}
onClick={(event) => console.log(item, index, event)}
>
{item}
</li>
))}
</ul>
</div>
);
}
Define function handler.
import { MouseEvent } from "react";
function ListGroup() {
const items = ["New York", "San Francisco", "Tokyo", "London", "Paris"];
const handleClick = (event: MouseEvent) => {
console.log(event);
};
return (
<div>
<h1>List</h1>
{items.length === 0 && <p>No item found</p>}
<ul className="list-group">
{items.map((item) => (
<li
className="list-group-item"
key={item}
onClick={handleClick}
>
{item}
</li>
))}
</ul>
</div>
);
}
import { MouseEvent } from "react";
function ListGroup() {
const items = ["New York", "San Francisco", "Tokyo", "London", "Paris"];
const handleClick = (item: string, index: number, event: MouseEvent) => {
console.log(item, index, event);
};
return (
<div>
<h1>List</h1>
{items.length === 0 && <p>No item found</p>}
<ul className="list-group">
{items.map((item, index) => (
<li
className="list-group-item"
key={item}
onClick={(event) => handleClick(item, index, event)}
>
{item}
</li>
))}
</ul>
</div>
);
}
Managing State
import { useState } from "react";
function ListGroup() {
const items = ["New York", "San Francisco", "Tokyo", "London", "Paris"];
const [selectedIndex, setSelectedIndex] = useState(-1);
return (
<div>
<h1>List</h1>
{items.length === 0 && <p>No item found</p>}
<ul className="list-group">
{items.map((item, index) => (
<li
className={
selectedIndex === index
? "list-group-item active"
: "list-group-item"
}
key={item}
onClick={() => {setSelectedIndex(index)}}
>
{item}
</li>
))}
</ul>
</div>
);
}
export default ListGroup;
Passing Data via Props
Using interface
import { useState } from "react";
interface Props {
items: string[];
heading: string;
}
function ListGroup({ items, heading }: Props) {
const [selectedIndex, setSelectedIndex] = useState(-1);
return (
<div>
<h1>{heading}</h1>
{items.length === 0 && <p>No item found</p>}
<ul className="list-group">
{items.map((item, index) => (
<li
className={
selectedIndex === index
? "list-group-item active"
: "list-group-item"
}
key={item}
onClick={() => {setSelectedIndex(index)}}
>
{item}
</li>
))}
</ul>
</div>
);
}
export default ListGroup;
import ListGroup from './components/ListGroup';
function App() {
const items = ["New York", "San Francisco", "Tokyo", "London", "Paris"];
return (
<div>
<ListGroup items={items} heading="Cities" />
</div>
);
}
export default App;
Passing Functions via Props
import { useState } from "react";
interface Props {
items: string[];
heading: string;
onSelectItem: (item: string) => void;
}
function ListGroup({ items, heading, onSelectItem }: Props) {
const [selectedIndex, setSelectedIndex] = useState(-1);
return (
<div>
<h1>{heading}</h1>
{items.length === 0 && <p>No item found</p>}
<ul className="list-group">
{items.map((item, index) => (
<li
className={
selectedIndex === index
? "list-group-item active"
: "list-group-item"
}
key={item}
onClick={() => {
setSelectedIndex(index);
onSelectItem(item);
}}
>
{item}
</li>
))}
</ul>
</div>
);
}
export default ListGroup;
import ListGroup from './components/ListGroup';
function App() {
const items = ["New York", "San Francisco", "Tokyo", "London", "Paris"];
const handleSelectItem = (item: string) => {
console.log(item);
};
return (
<div>
<ListGroup items={items} heading="Cities" onSelectItem={handleSelectItem} />
</div>
);
}
export default App;
State vs Props
Props
- Input passed to a component.
- Similar to function args.
- Immutable: can not change inside function, this is call functional programming principles.
State:
- Data managed by a component.
- Similar to local variables.
- Mutable
When they changed, Both will re-render component and update the Dom accordingly.
ES7 React
Cursor install plugin ES7 React. And input rafce.
reactArrowFunctionExportComponent
Passing Children
All components support children prop. children prop can be any type, such as:
stringReactNodefor html content.
interface Props {
children: React.ReactNode;
}
function Alert({ children }: Props) {
return <div className="alert alert-primary">{children}</div>;
}
export default Alert;
import Alert from './components/Alert';
function App() {
return (
<div>
<Alert>
Hello World <span>YEAH</span>
</Alert>
</div>
);
}
export default App;
Inspecting Components with React Dev Tools
Inspect the matching DOM element.

View source code for this element.

No comments to display
No comments to display