Настройка проекта Redux для интеграции
Перед тем как начать, убедитесь, что ваш проект настроен для работы с Redux. Если вы пропустили предыдущие лекции, выполните команду для установки Redux Toolkit:
npm install @reduxjs/toolkit react-redux
Также убедитесь, что уже подключили хранилище (store) в корневом компоненте приложения:
import React from 'react';
import { Provider } from 'react-redux';
import { store } from './store';
export default function App() {
return (
<Provider store={store}>
<YourApp />
</Providerv
);
}
Если это уже сделано, поехали дальше!
Используем useSelector для получения данных из состояния
useSelector – это хук, который позволяет извлекать данные из глобального состояния Redux. Он ведёт себя как магнит, вытаскивая нужные куски данных из хранилища. Давайте посмотрим на практический пример.
Пример: отображение имени пользователя
Мы будем использовать срез userSlice, который содержит информацию о текущем пользователе.
Создаём срез (если его ещё нет):
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
interface UserState {
name: string;
age: number;
}
const initialState: UserState = {
name: 'Гость',
age: 0
};
const userSlice = createSlice({
name: 'user',
initialState,
reducers: {
setName(state, action: PayloadAction<string>) {
state.name = action.payload;
},
setAge(state, action: PayloadAction<numberv) {
state.age = action.payload;
},
},
});
export const { setName, setAge } = userSlice.actions;
export default userSlice.reducer;
Подключаем срез в хранилище:
import { configureStore } from '@reduxjs/toolkit';
import userReducer from './features/user/userSlice';
export const store = configureStore({
reducer: {
user: userReducer,
},
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
Используем в компоненте с хуком useSelector:
import React from 'react';
import { Text } from 'react-native';
import { useSelector } from 'react-redux';
import { RootState } from './store';
function UserInfo() {
const userName = useSelector((state: RootState) => state.user.name);
return <Text>Привет, {userName}!</Text>;
}
export default UserInfo;
Теперь, если вы измените значение name в состоянии, компонент автоматически обновится. Это магия связи компонентов с Redux!
Используем useDispatch для изменения состояния
useDispatch – это хук, который позволяет отправлять действия (actions) для изменения глобального состояния в хранилище. Если useSelector – это глаза, то useDispatch – это руки, выполняющие действия.
Пример: обновление имени пользователя
Добавим функциональность для ввода нового имени пользователя.
Пример компонента:
import React, { useState } from 'react';
import { TextInput, Button, View } from 'react-native';
import { useDispatch } from 'react-redux';
import { setName } from './features/user/userSlice';
function UpdateUserName() {
const [newName, setNewName] = useState('');
const dispatch = useDispatch();
const handleUpdateName = () => {
if (newName.trim()) {
dispatch(setName(newName)); // Отправляем действие, чтобы изменить имя
setNewName('');
}
};
return (
<View>
<TextInput
value={newName}
onChangeText={setNewName}
placeholder="Введите ваше имя"
/>
<Button title="Обновить имя" onPress={handleUpdateName} />
</View>
);
}
export default UpdateUserName;
Теперь наше приложение позволяет пользователю обновить своё имя! Если вы соедините этот компонент с предыдущим, то увидите, как UserInfo обновляется в реальном времени.
Практический пример: комбинируем useSelector и useDispatch
Давайте объединим всё, что вы узнали, в один компонент.
Задача: управлять счётчиком
- Создайте в вашем срезе новый раздел для счётчика:
const counterSlice = createSlice({ name: 'counter', initialState: { value: 0 }, reducers: { increment: (state) => { state.value += 1; }, decrement: (state) => { state.value -= 1; }, }, }); export const { increment, decrement } = counterSlice.actions; export default counterSlice.reducer;
- Обновите
storeдля подключенияcounterSlice:import counterReducer from './features/counter/counterSlice'; export const store = configureStore({ reducer: { user: userReducer, counter: counterReducer, }, });
- Создайте компонент
Counter:import React from 'react'; import { Text, Button, View } from 'react-native'; import { useSelector, useDispatch } from 'react-redux'; import { RootState } from './store'; import { increment, decrement } from './features/counter/counterSlice'; function Counter() { const count = useSelector((state: RootState) => state.counter.value); const dispatch = useDispatch(); return ( <View> <Text>Счётчик: {count}</Text> <Button title="Увеличить" onPress={() => dispatch(increment())} /> <Button title="Уменьшить" onPress={() => dispatch(decrement())} /> </View> ); } export default Counter;
Поздравляю, вы только что создали полностью функциональный компонент с глобальным состоянием! Этот компонент можно использовать в любом месте приложения, и он всегда будет синхронизироваться с состоянием в Redux.
Советы и типичные ошибки
При интеграции Redux с компонентами важно помнить:
- Не запрашивайте больше данных, чем нужно. Выводите только те части состояния, которые вам необходимы, чтобы избежать лишних рендеров.
- Не вызывайте dispatch внутри рендера. Это одна из самых распространённых ошибок.
- Следите за производительностью. Если ваше состояние становится слишком большим, используйте мемоизацию с
useMemoилиReact.memo.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ