跳到主要内容

实际应用

函数式编程在实际项目中有广泛的应用,本章介绍几个常见的使用场景。

React 中的函数式编程

函数组件

// 纯函数组件
const UserCard = ({ name, email, avatar }) => (
<div className="user-card">
<img src={avatar} alt={name} />
<h3>{name}</h3>
<p>{email}</p>
</div>
);

Hooks

import { useState, useCallback, useMemo } from 'react';

const UserList = ({ users }) => {
const [filter, setFilter] = useState('');

// 纯函数处理数据
const filteredUsers = useMemo(() =>
users
.filter(u => u.name.toLowerCase().includes(filter.toLowerCase()))
.sort((a, b) => a.name.localeCompare(b.name)),
[users, filter]
);

const handleFilterChange = useCallback((e) => {
setFilter(e.target.value);
}, []);

return (
<div>
<input
value={filter}
onChange={handleFilterChange}
placeholder="Search users..."
/>
<ul>
{filteredUsers.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
};

Redux 中的函数式编程

// Action Creators
const addTodo = text => ({
type: 'ADD_TODO',
payload: { id: Date.now(), text, completed: false }
});

// Pure Reducer
const todosReducer = (state = [], action) => {
switch (action.type) {
case 'ADD_TODO':
return [...state, action.payload];
case 'TOGGLE_TODO':
return state.map(todo =>
todo.id === action.payload
? { ...todo, completed: !todo.completed }
: todo
);
default:
return state;
}
};

// Selector
const getCompletedTodos = state =>
state.todos.filter(todo => todo.completed);

数据处理

数据转换管道

const processApiResponse = R.pipe(
R.prop('data'),
R.map(R.pick(['id', 'name', 'email'])),
R.filter(R.propSatisfies(R.complement(R.isEmpty), 'email')),
R.sortBy(R.prop('name'))
);

// 使用
const users = processApiResponse(apiResponse);

表单验证

const validators = {
required: msg => value =>
!value || value.trim() === '' ? msg : null,

minLength: (min, msg) => value =>
value && value.length < min ? msg : null,

email: msg => value =>
value && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) ? msg : null
};

const validate = rules => value =>
rules.reduce((error, rule) => error || rule(value), null);

// 使用
const emailValidator = validate([
validators.required('Email is required'),
validators.email('Invalid email format')
]);

emailValidator('[email protected]'); // null (valid)
emailValidator('invalid'); // 'Invalid email format'

异步流程控制

Promise 组合

const fetchUser = id => fetch(`/api/users/${id}`).then(r => r.json());
const fetchPosts = userId => fetch(`/api/posts?userId=${userId}`).then(r => r.json());

const getUserWithPosts = async (userId) => {
const user = await fetchUser(userId);
const posts = await fetchPosts(user.id);
return { ...user, posts };
};

// 函数式风格
const getUserWithPosts = userId =>
Promise.resolve(userId)
.then(fetchUser)
.then(user =>
fetchPosts(user.id).then(posts => ({ ...user, posts }))
);

测试

纯函数易于测试:

// 纯函数 - 容易测试
describe('calculateTotal', () => {
it('should calculate total with tax', () => {
expect(calculateTotal(100, 0.1)).toBe(110);
expect(calculateTotal(50, 0.2)).toBe(60);
});
});

// 不纯函数 - 需要 mock
describe('saveToDatabase', () => {
it('should save data', async () => {
const mockDb = { save: jest.fn() };
await saveToDatabase(mockDb, data);
expect(mockDb.save).toHaveBeenCalledWith(data);
});
});

最佳实践

  1. 分离纯函数和不纯函数
  2. 使用不可变数据
  3. 组合小函数构建复杂逻辑
  4. 利用类型系统(TypeScript/Flow)