React组件API知识点汇总
编程小白的通俗易懂指南 – 从零开始掌握React核心概念
React组件基础知识
什么是React组件?
组件就像乐高积木,是构建React应用的独立模块。每个组件代表UI的一部分,可以重复使用。
函数组件
使用JavaScript函数定义,更简洁,推荐使用
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
return <h1>Hello, {props.name}</h1>;
}
类组件
使用ES6类定义,以前更常见,现在逐渐被函数组件取代
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
Props(属性)
Props 是组件之间传递数据的方式,就像函数的参数。
- 只读:组件不能修改自己的props
- 用于父组件向子组件传递数据
- 可以是任何JavaScript值:字符串、数字、对象、函数等
// 父组件传递props
<User name=”张三” age={25} />
// 子组件接收props
function User(props) {
return (
<div>
姓名:{props.name},年龄:{props.age}
</div>
);
}
<User name=”张三” age={25} />
// 子组件接收props
function User(props) {
return (
<div>
姓名:{props.name},年龄:{props.age}
</div>
);
}
State(状态)
State 是组件内部的数据,当状态改变时,组件会重新渲染。
- 使用useState Hook管理状态(函数组件)
- 使用this.state和this.setState(类组件)
- 状态改变触发UI更新
重要区别:Props vs State
- Props:从外部传入,组件不能修改(只读)
- State:组件内部管理,可以修改(使用setState或useState)
React Hooks详解
Hooks是React 16.8引入的新特性,允许你在函数组件中使用状态和其他React特性。
useState
用于在函数组件中添加状态
const [count, setCount] = useState(0);
// 使用
<button onClick={() => setCount(count + 1)}>
点击次数: {count}
</button>
// 使用
<button onClick={() => setCount(count + 1)}>
点击次数: {count}
</button>
useEffect
处理副作用(数据获取、订阅、手动操作DOM)
useEffect(() => {
// 组件挂载或更新时执行
document.title = `你点击了 ${count} 次`;
// 清理函数(组件卸载时执行)
return () => {
document.title = ‘React App’;
};
}, [count]); // 依赖数组
// 组件挂载或更新时执行
document.title = `你点击了 ${count} 次`;
// 清理函数(组件卸载时执行)
return () => {
document.title = ‘React App’;
};
}, [count]); // 依赖数组
useContext
访问React上下文(Context),避免多层传递props
// 创建上下文
const ThemeContext = React.createContext(‘light’);
// 提供值
<ThemeContext.Provider value=”dark”>
<App />
</ThemeContext.Provider>
// 使用值
const theme = useContext(ThemeContext);
const ThemeContext = React.createContext(‘light’);
// 提供值
<ThemeContext.Provider value=”dark”>
<App />
</ThemeContext.Provider>
// 使用值
const theme = useContext(ThemeContext);
useRef
创建可变的引用对象,常用于访问DOM元素
const inputRef = useRef();
useEffect(() => {
inputRef.current.focus();
}, []);
return <input ref={inputRef} />;
useEffect(() => {
inputRef.current.focus();
}, []);
return <input ref={inputRef} />;
自定义Hooks
可以将组件逻辑提取到可重用的函数中:
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener(‘resize’, handleResize);
return () => window.removeEventListener(‘resize’, handleResize);
}, []);
return width;
}
// 使用自定义Hook
const width = useWindowWidth();
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener(‘resize’, handleResize);
return () => window.removeEventListener(‘resize’, handleResize);
}, []);
return width;
}
// 使用自定义Hook
const width = useWindowWidth();
组件生命周期方法
组件的生命周期指的是组件从创建到销毁的整个过程。React提供了特定的方法(生命周期方法)让我们在关键节点执行代码。
组件生命周期示意图
挂载 → 更新 → 卸载
挂载
(constructor, render, componentDidMount)
(constructor, render, componentDidMount)
更新
(shouldComponentUpdate, render, componentDidUpdate)
(shouldComponentUpdate, render, componentDidUpdate)
卸载
(componentWillUnmount)
(componentWillUnmount)
类组件生命周期方法
componentDidMount
组件挂载后(插入DOM树中)立即调用
适合进行网络请求、设置订阅等操作
componentDidUpdate
更新后立即调用(首次渲染不会执行)
适合在更新后操作DOM或发送网络请求
componentWillUnmount
组件卸载及销毁之前调用
适合进行清理操作(取消网络请求、移除订阅等)
函数组件的”生命周期”
函数组件中没有生命周期方法,但可以使用Hooks模拟类似行为:
- componentDidMount:useEffect(fn, [])
- componentDidUpdate:useEffect(fn, [deps])
- componentWillUnmount:useEffect(() => { return fn }, [])
避免常见的生命周期错误
- 在componentDidMount中设置定时器,必须在componentWillUnmount中清除
- 在componentDidUpdate中更新状态时要小心,避免无限循环
- 使用useEffect时,注意依赖数组的配置
React高级组件API
当你熟悉React基础后,这些高级API能帮你解决更复杂的问题
Context API
Context提供了一个无需为每层组件手动添加props,就能在组件树间进行数据传递的方法
// 1. 创建Context
const UserContext = React.createContext();
// 2. 提供Context值
function App() {
return (
<UserContext.Provider value=”张三”>
<Toolbar />
</UserContext.Provider>
);
}
// 3. 在子组件中消费Context
function Toolbar() {
return (
<div>
<UserInfo />
</div>
);
}
function UserInfo() {
const user = useContext(UserContext);
return <div>当前用户: {user}</div>;
}
const UserContext = React.createContext();
// 2. 提供Context值
function App() {
return (
<UserContext.Provider value=”张三”>
<Toolbar />
</UserContext.Provider>
);
}
// 3. 在子组件中消费Context
function Toolbar() {
return (
<div>
<UserInfo />
</div>
);
}
function UserInfo() {
const user = useContext(UserContext);
return <div>当前用户: {user}</div>;
}
Refs和DOM操作
Refs提供了一种访问DOM节点或在组件实例之间共享可变值的方式
function TextInput() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<>
<input ref={inputRef} type=”text” />
<button onClick={focusInput}>聚焦输入框</button>
</>
);
}
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<>
<input ref={inputRef} type=”text” />
<button onClick={focusInput}>聚焦输入框</button>
</>
);
}
错误边界(Error Boundaries)
错误边界是一种React组件,可以捕获其子组件树中的JavaScript错误,并显示备用UI
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// 可以记录错误到日志系统
logErrorToService(error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>出现错误,请刷新页面</h1>;
}
return this.props.children;
}
}
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// 可以记录错误到日志系统
logErrorToService(error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>出现错误,请刷新页面</h1>;
}
return this.props.children;
}
}
React组件实战示例
示例1:计数器组件
import { useState } from ‘react’;
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<h3>当前计数: {count}</h3>
<button onClick={() => setCount(count + 1)}>增加</button>
<button onClick={() => setCount(count – 1)}>减少</button>
<button onClick={() => setCount(0)}>重置</button>
</div>
);
}
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<h3>当前计数: {count}</h3>
<button onClick={() => setCount(count + 1)}>增加</button>
<button onClick={() => setCount(count – 1)}>减少</button>
<button onClick={() => setCount(0)}>重置</button>
</div>
);
}
示例2:Todo列表
function TodoList() {
const [todos, setTodos] = useState([
{ id: 1, text: ‘学习React’, completed: true },
{ id: 2, text: ‘写一个项目’, completed: false }
]);
const [input, setInput] = useState(”);
const addTodo = () => {
if (input.trim() === ”) return;
setTodos([…todos, { id: Date.now(), text: input, completed: false }]);
setInput(”);
};
const toggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id ? { …todo, completed: !todo.completed } : todo
));
};
return (
<div>
<h2>Todo列表</h2>
<input
value={input}
onChange={e => setInput(e.target.value)}
placeholder=”添加新任务”
/>
<button onClick={addTodo}>添加</button>
<ul>
{todos.map(todo => (
<li key={todo.id}>
<input
type=”checkbox”
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
<span style={{ textDecoration: todo.completed ? ‘line-through’ : ‘none’ }}>
{todo.text}
</span>
</li>
))}
</ul>
</div>
);
}
const [todos, setTodos] = useState([
{ id: 1, text: ‘学习React’, completed: true },
{ id: 2, text: ‘写一个项目’, completed: false }
]);
const [input, setInput] = useState(”);
const addTodo = () => {
if (input.trim() === ”) return;
setTodos([…todos, { id: Date.now(), text: input, completed: false }]);
setInput(”);
};
const toggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id ? { …todo, completed: !todo.completed } : todo
));
};
return (
<div>
<h2>Todo列表</h2>
<input
value={input}
onChange={e => setInput(e.target.value)}
placeholder=”添加新任务”
/>
<button onClick={addTodo}>添加</button>
<ul>
{todos.map(todo => (
<li key={todo.id}>
<input
type=”checkbox”
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
<span style={{ textDecoration: todo.completed ? ‘line-through’ : ‘none’ }}>
{todo.text}
</span>
</li>
))}
</ul>
</div>
);
}
学习React的最佳实践
- 将UI拆分为小的可复用组件
- 使用函数组件和Hooks
- 状态提升:将共享状态提升到最近的共同祖先组件
- 使用key属性优化列表渲染性能
- 避免过早优化