大家好,我是小杨,一名有6年经验的前端开发工程师。在React开发中,状态(State)和参数(Props)的修改是最基础但也最容易踩坑的部分。今天我就来分享几种常见的React参数修改方法,以及我在项目中总结的最佳实践,避免大家走弯路。
1. 直接修改State?大忌!
新手常犯的一个错误是直接修改state
,比如:
// ❌ 错误示范:直接修改state
this.state.count = 10;
React的state
是不可变(Immutable) 的,直接修改不会触发重新渲染。正确的做法是使用setState
(类组件)或useState
的更新函数(函数组件)。
2. 类组件:setState的正确姿势
在类组件里,修改状态必须用setState
:
class Counter extends React.Component {
state = { count: 0 };
increment = () => {
// ✅ 正确方式:使用setState
this.setState({ count: this.state.count + 1 });
};
render() {
return <button onClick={this.increment}>Count: {this.state.count}</button>;
}
}
注意:setState
是异步的,如果依赖前一个状态,应该用函数式更新:
this.setState((prevState) => ({ count: prevState.count + 1 }));
3. 函数组件:useState + 不可变更新
在函数组件里,我们使用useState
,同样要遵循不可变原则:
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const increment = () => {
// ✅ 正确方式:使用useState的更新函数
setCount(count + 1);
};
return <button onClick={increment}>Count: {count}</button>;
}
如果新状态依赖旧状态,推荐使用函数式更新:
setCount((prevCount) => prevCount + 1);
4. 修改对象或数组:避免引用突变
React要求状态更新必须是不可变的,所以直接修改对象或数组的属性是不行的:
const [user, setUser] = useState({ name: 'Alice', age: 25 });
// ❌ 错误:直接修改对象
user.age = 26;
setUser(user); // 不会触发更新!
// ✅ 正确:创建新对象
setUser({ ...user, age: 26 });
数组的更新也要遵循不可变原则:
const [todos, setTodos] = useState(['Learn React', 'Write Blog']);
// ✅ 正确:使用展开运算符或map/filter
setTodos([...todos, 'New Task']); // 添加
setTodos(todos.filter((todo) => todo !== 'Learn React')); // 删除
5. 性能优化:useState vs useReducer
如果状态逻辑较复杂,useState
可能会变得臃肿,这时可以用useReducer
:
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error('Unknown action');
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
Count: {state.count}
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
</div>
);
}
useReducer
适合管理复杂状态逻辑,比如表单、全局状态等。
6. 常见坑点 & 解决方案
① 连续setState不会立即更新
// ❌ 连续调用setState,count只会+1
setCount(count + 1);
setCount(count + 1);
// ✅ 使用函数式更新
setCount(prev => prev + 1);
setCount(prev => prev + 1); // 现在会+2
② useEffect依赖问题
如果useEffect
依赖state
,但忘记加进依赖数组,可能导致闭包问题:
useEffect(() => {
console.log(count); // 可能拿到旧值
}, []); // ❌ 缺少依赖
useEffect(() => {
console.log(count); // ✅ 正确
}, [count]); // 依赖正确
总结
- 不要直接修改
state
,使用setState
或useState
的更新函数 - 对象/数组更新时,创建新引用
- 复杂状态逻辑用
useReducer
- 连续更新用函数式
setState
useEffect
依赖要写全
⭐ 写在最后
请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.
✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式
✅ 认为我部分代码过于老旧,可以提供新的API或最新语法
✅ 对于文章中部分内容不理解
✅ 解答我文章中一些疑问
✅ 认为某些交互,功能需要优化,发现BUG
✅ 想要添加新功能,对于整体的设计,外观有更好的建议
✅ 一起探讨技术加qq交流群:906392632
最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!