Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое Action?
Action — это концепция, которая используется в различных контекстах Frontend-разработки. Чаще всего она связана с управлением состоянием приложения. Рассмотрим основные значения.
Action в Redux
В Redux Action — это простой JavaScript объект, который описывает, что произошло в приложении:
const action = {
type: 'USER_LOGGED_IN',
payload: {
userId: 123,
username: 'alice'
}
};
Ключевые свойства Action:
- type — обязательное поле, описывает тип события
- payload — данные, передаваемые с экшеном (опционально)
Workflow с Action
Action используется в цепочке Redux:
// 1. Компонент dispatch-ит action
function LoginButton() {
const dispatch = useDispatch();
const handleLogin = () => {
dispatch({
type: 'USER_LOGGED_IN',
payload: { userId: 123, username: 'alice' }
});
};
return <button onClick={handleLogin}>Login</button>;
}
// 2. Reducer получает action и обновляет state
function authReducer(state = {}, action) {
switch (action.type) {
case 'USER_LOGGED_IN':
return { ...state, user: action.payload };
case 'USER_LOGGED_OUT':
return { ...state, user: null };
default:
return state;
}
}
Action Creator
Функция, которая создаёт action объект:
// Action Creator
const userLoggedIn = (userId, username) => ({
type: 'USER_LOGGED_IN',
payload: { userId, username }
});
const userLoggedOut = () => ({
type: 'USER_LOGGED_OUT'
});
// Использование
dispatch(userLoggedIn(123, 'alice'));
dispatch(userLoggedOut());
Async Action (Thunk)
Для асинхронных операций используются Thunk Action Creator:
// Thunk
const loginUser = (credentials) => async (dispatch) => {
dispatch({ type: 'LOGIN_START' });
try {
const response = await fetch('/api/login', {
method: 'POST',
body: JSON.stringify(credentials)
});
const data = await response.json();
dispatch({
type: 'LOGIN_SUCCESS',
payload: data
});
} catch (error) {
dispatch({
type: 'LOGIN_ERROR',
payload: error.message
});
}
};
// Использование
dispatch(loginUser({ email: 'john@example.com', password: '...' }));
Action в React Context
В Context API + useReducer действия выглядят похоже:
const initialState = { user: null, loading: false };
function authReducer(state, action) {
switch (action.type) {
case 'LOGIN_REQUEST':
return { ...state, loading: true };
case 'LOGIN_SUCCESS':
return { ...state, user: action.payload, loading: false };
case 'LOGIN_ERROR':
return { ...state, error: action.payload, loading: false };
default:
return state;
}
}
function AuthProvider({ children }) {
const [state, dispatch] = useReducer(authReducer, initialState);
const login = async (credentials) => {
dispatch({ type: 'LOGIN_REQUEST' });
try {
const user = await fetchUser(credentials);
dispatch({ type: 'LOGIN_SUCCESS', payload: user });
} catch (error) {
dispatch({ type: 'LOGIN_ERROR', payload: error.message });
}
};
return (
<AuthContext.Provider value={{ state, login }}>
{children}
</AuthContext.Provider>
);
}
Action в Next.js Server Actions
В Next.js 13+ Server Actions — это функции, выполняемые на сервере:
// app/actions.ts
'use server';
export async function updateUserProfile(formData) {
const name = formData.get('name');
const email = formData.get('email');
const response = await db.users.update({
name,
email
});
revalidatePath('/profile');
return response;
}
// app/profile/page.tsx
import { updateUserProfile } from '@/app/actions';
export default function ProfilePage() {
return (
<form action={updateUserProfile}>
<input name="name" />
<input name="email" />
<button type="submit">Update</button>
</form>
);
}
Action как обработчик событий
В HTML/JavaScript, Action иногда означает функцию-обработчик:
// React
function Button() {
const handleClick = () => {
console.log('Button clicked');
};
return <button onClick={handleClick}>Click me</button>;
}
// Или в HTML форме
<form onSubmit={(e) => handleSubmit(e)}>
<input type="text" />
<button type="submit">Send</button>
</form>
Типизация Action в TypeScript
type Action =
| { type: 'USER_LOGGED_IN'; payload: { userId: number; username: string } }
| { type: 'USER_LOGGED_OUT' }
| { type: 'SET_LOADING'; payload: boolean };
function reducer(state: State, action: Action): State {
switch (action.type) {
case 'USER_LOGGED_IN':
return { ...state, user: action.payload };
case 'USER_LOGGED_OUT':
return { ...state, user: null };
case 'SET_LOADING':
return { ...state, loading: action.payload };
}
}
Best Practices для Action
1. Единственная ответственность
// Плохо — слишком много в одном action
{ type: 'COMPLEX_UPDATE', payload: { user, posts, comments } }
// Хорошо — отдельные действия
{ type: 'UPDATE_USER', payload: user }
{ type: 'UPDATE_POSTS', payload: posts }
2. Нормализованные имена типов
// ✅
'USER_LOADED'
'POST_CREATED'
'COMMENT_DELETED'
// ❌
'load_user'
'createPost'
'delete-comment'
3. Не мутируй state в reducer
// Плохо
state.user.name = 'New Name';
// Хорошо
return { ...state, user: { ...state.user, name: 'New Name' } };
Заключение
Action — это описание события или команда к изменению состояния в приложении. Это концепция, которая используется в:
- Redux — для управления глобальным состоянием
- Context API + useReducer — для локального управления состоянием
- Next.js Server Actions — для выполнения операций на сервере
- HTML/JavaScript — просто как обработчик события
Понимание Action критично для работы с современным состоянием в React приложениях.