前端状态管理:Recoil的原子世界

前端状态管理:Recoil的原子世界

毒舌时刻

前端状态管理?Redux不是已经够了吗?

"Redux太复杂了,我用Context API就够了"——结果状态管理混乱,性能差,
"Zustand简单,我用Zustand"——结果复杂状态难以管理,
"Recoil?没听说过,肯定不如Redux"——结果错过了更优雅的状态管理方案。

醒醒吧,Recoil不是Redux的替代品,而是一种更现代化的状态管理方案!

为什么你需要这个?

  • 原子化状态:将状态拆分为最小的原子单位,更灵活
  • 派生状态:通过选择器创建派生状态,减少重复计算
  • React集成:与React Hooks无缝集成,使用更自然
  • 性能优化:只重新渲染依赖状态变化的组件

反面教材

// 反面教材:使用Context API管理复杂状态 import React, { createContext, useContext, useState, useReducer } from 'react'; // 创建Context const AppContext = createContext(); // 复杂的reducer function reducer(state, action) { switch (action.type) { case 'SET_USER': return { ...state, user: action.payload }; case 'SET_TODOS': return { ...state, todos: action.payload }; case 'ADD_TODO': return { ...state, todos: [...state.todos, action.payload] }; case 'TOGGLE_TODO': return { ...state, todos: state.todos.map(todo => todo.id === action.payload ? { ...todo, completed: !todo.completed } : todo ) }; // 更多action... default: return state; } } // Provider组件 function AppProvider({ children }) { const [state, dispatch] = useReducer(reducer, { user: null, todos: [], loading: false, error: null }); return ( <AppContext.Provider value={{ state, dispatch }}> {children} </AppContext.Provider> ); } // 使用Context function TodoList() { const { state, dispatch } = useContext(AppContext); // 每次状态变化都会重新渲染,即使只关心todos return ( <div> {state.todos.map(todo => ( <div key={todo.id}> <input type="checkbox" checked={todo.completed} onChange={() => dispatch({ type: 'TOGGLE_TODO', payload: todo.id })} /> {todo.text} </div> ))} </div> ); } 

正确的做法

// 正确的做法:使用Recoil import React from 'react'; import { atom, selector, useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'; // 定义原子状态 const userState = atom({ key: 'userState', default: null }); const todosState = atom({ key: 'todosState', default: [] }); const loadingState = atom({ key: 'loadingState', default: false }); // 定义派生状态 const completedTodosState = selector({ key: 'completedTodosState', get: ({ get }) => { const todos = get(todosState); return todos.filter(todo => todo.completed); } }); const incompleteTodosState = selector({ key: 'incompleteTodosState', get: ({ get }) => { const todos = get(todosState); return todos.filter(todo => !todo.completed); } }); const todoStatsState = selector({ key: 'todoStatsState', get: ({ get }) => { const todos = get(todosState); const completed = get(completedTodosState); const incomplete = get(incompleteTodosState); return { total: todos.length, completed: completed.length, incomplete: incomplete.length, completionRate: todos.length > 0 ? (completed.length / todos.length) * 100 : 0 }; } }); // 使用Recoil状态 function TodoList() { // 只订阅todosState,其他状态变化不会触发重新渲染 const [todos, setTodos] = useRecoilState(todosState); const toggleTodo = (id) => { setTodos(todos.map(todo => todo.id === id ? { ...todo, completed: !todo.completed } : todo )); }; return ( <div> {todos.map(todo => ( <div key={todo.id}> <input type="checkbox" checked={todo.completed} onChange={() => toggleTodo(todo.id)} /> {todo.text} </div> ))} </div> ); } function TodoStats() { // 只订阅派生状态,当依赖的状态变化时才会重新渲染 const stats = useRecoilValue(todoStatsState); return ( <div> <p>总任务数:{stats.total}</p> <p>已完成:{stats.completed}</p> <p>未完成:{stats.incomplete}</p> <p>完成率:{stats.completionRate.toFixed(2)}%</p> </div> ); } function AddTodo() { // 只订阅setter函数,不会因为状态变化而重新渲染 const setTodos = useSetRecoilState(todosState); const [text, setText] = React.useState(''); const handleSubmit = (e) => { e.preventDefault(); if (text.trim()) { setTodos(prev => [...prev, { id: Date.now(), text, completed: false }]); setText(''); } }; return ( <form onSubmit={handleSubmit}> <input type="text" value={text} onChange={(e) => setText(e.target.value)} placeholder="添加任务" /> <button type="submit">添加</button> </form> ); } function UserProfile() { const [user, setUser] = useRecoilState(userState); const [loading, setLoading] = useRecoilState(loadingState); React.useEffect(() => { setLoading(true); // 模拟API请求 setTimeout(() => { setUser({ id: 1, name: '张三', email: '[email protected]' }); setLoading(false); }, 1000); }, [setUser, setLoading]); if (loading) { return <div>加载中...</div>; } return ( <div> <h2>用户信息</h2> {user ? ( <div> <p>姓名:{user.name}</p> <p>邮箱:{user.email}</p> </div> ) : ( <p>未登录</p> )} </div> ); } // 主应用 function App() { return ( <div> <h1>Recoil状态管理示例</h1> <UserProfile /> <AddTodo /> <TodoList /> <TodoStats /> </div> ); } 

毒舌点评

看看,这才叫前端状态管理!不是简单地使用Context API或Redux,而是使用Recoil的原子化状态管理,让状态管理更加清晰和高效。

记住,Recoil的优势在于它的原子化和派生状态,这使得状态管理更加灵活和可扩展。它与React Hooks的无缝集成,让使用起来更加自然。

所以,别再固守传统的状态管理方案了,Recoil为你打开了一个全新的原子世界!

总结

  • 原子状态:使用atom定义最小的状态单位
  • 派生状态:使用selector创建基于原子状态的派生状态
  • React集成:使用useRecoilStateuseRecoilValueuseSetRecoilState等Hooks
  • 性能优化:只重新渲染依赖状态变化的组件
  • 状态持久化:可以与localStorage等结合实现状态持久化
  • 调试工具:使用Recoil DevTools进行状态调试
  • 类型支持:完整的TypeScript类型支持
  • 可扩展性:适合从小型应用到大型应用的各种场景

Recoil,让前端状态管理变得更加优雅!

Read more

【论文阅读】SWE-CI: Evaluating Agent Capabilities in Maintaining Codebases via Continuous Integration

【论文阅读】SWE-CI: Evaluating Agent Capabilities in Maintaining Codebases via Continuous Integration

SWE-CI:基于持续集成评估智能体在代码库维护中的能力 * 论文链接 * 摘要 * 1. 简介 * 2. 评估智能体维护代码库的能力 * 2.1 任务形式化 * 2.2 归一化变更 * 2.3 EvoScore(演进得分) * 3 SWE-CI * 3.1 数据构建(Data curation) * Step 1: Repository Collection * Step 2: Commit Span Extraction * Step 3: Environment Construction * Step 4: Case Filtering * 3.2 双智能体评估协议 * 4 Experiments * 4.1 Experiment

空天地联动 | 一网统飞 | 无人机巡检系统落地方案

空天地联动 | 一网统飞 | 无人机巡检系统落地方案

一、政策需求 国家将低空经济列为战略性新兴产业,“十五五” 规划明确推进一网统飞、低空智治全国覆盖,要求 2026 年前实现地市一级飞行数据全接入、空域审批一体化、低空监管数字化。多部委联合发文,推动低空通信、导航、感知基础设施建设,规范无人机飞行与空域管理,鼓励以统一平台、统一调度、统一数据模式支撑政务巡检、应急救援、生态环保、城市治理等场景规模化落地,加速低空经济从试点走向全域普及。 二、市场需求与行业痛点 1. 空域管理分散,审批效率低:多部门分头审批、流程繁琐,跨区域飞行难,“黑飞”、乱飞风险突出,安全监管压力大。 2. 部门各自为战,资源浪费严重:各单位自建系统、自购设备,重复飞行、重复投入,财政成本高、资源利用率低。 3. 数据孤岛普遍,价值难释放:巡检数据格式不统一、无法共享,难以支撑决策与协同处置。 4.

机器人-六轴机械臂的正运动学

机器人-六轴机械臂的正运动学

在机器人运动学建模领域,D-H(Denavit-Hartenberg)参数法绝对是绕不开的核心技术。它以极简的4个参数,就能清晰描述机械臂各连杆间的相对位姿关系,是实现正运动学求解、轨迹规划的基础。本文将从理论原理出发,一步步拆解六轴机械臂的D-H法建模流程,最后结合代码实现让理论落地,适合机器人初学者或技术爱好者深入学习。 一、为什么选择D-H法?—— 机械臂建模的“通用语言” 六轴机械臂作为工业场景中最常用的机器人构型,其连杆与关节的空间关系复杂。如果直接用三维坐标系叠加计算,不仅公式繁琐,还容易出现坐标混乱的问题。而D-H法的核心优势的在于“标准化”: * 简化参数:用仅4个参数(关节角、连杆偏移、连杆长度、连杆扭转角)描述相邻连杆的位姿,替代复杂的三维坐标变换; * 通用性强:适用于所有串联机械臂,无论是六轴、四轴还是协作机械臂,都能套用同一套建模逻辑; * 计算高效:通过齐次变换矩阵的乘积,可快速求解末端执行器相对于基坐标系的位姿,为后续运动学分析奠定基础。 简单来说,学会D-H法,就掌握了串联机械臂建模的“通用语言”。 二、D-H法核心:4个

Home Assistant界面美化终极指南:从零开始打造个性化智能家居界面

Home Assistant界面美化终极指南:从零开始打造个性化智能家居界面 【免费下载链接】frontend:lollipop: Frontend for Home Assistant 项目地址: https://gitcode.com/gh_mirrors/frontend149/frontend 想要让智能家居控制界面既美观又实用吗?Home Assistant提供了强大的界面定制功能,让你可以完全掌控界面的视觉风格。本指南将带你从基础设置到高级技巧,一步步打造专属于你的智能家居美学体验。 为什么你的Home Assistant界面需要美化? 界面美化不仅仅是改变颜色,它能显著提升你的智能家居使用体验: * 视觉舒适度:长时间使用不会造成眼睛疲劳 * 个性化表达:界面风格与你的家居装修完美融合 * 操作效率:优化的布局让控制更加直观便捷 * 多设备适配:确保在不同屏幕尺寸下都有最佳显示效果 快速上手:基础美化设置 如何访问主题设置界面 在Home Assistant主界面中,点击右上角的个人资料图标,选择"主题"选项,即可开始你的美化之旅。系统内置了多