前言
Redux Tookit 是官方出的 redux 工具,这里简单说一下使用的方法。
下文直接使用的是的 Typescirpt 的写法。
传送门
安装
yarn add @reduxjs/toolkit
yarn add react-redux
使用
新建目录结构如下:
├── src
│ ├── store
│ │ ├── slices
│ │ │ ├── counterSlice.ts
│ │ ├── hooks.ts
│ │ ├── store.ts
│ ├── App.tsx
创建 store
// src/store/store.ts
import {configureStore} from '@reduxjs/toolkit';
export const store = configureStore({
reducer: {},
});
使用 store
在入口文件最外层添加代码:
// src/App.tsx
import {Provider} from 'react-redux';
import {store} from '@store/store';
const App = () => {
return (
<Provider store={store}>
</Provider>
);
}
export default App;
创建 slice
// src/store/slices/counterSlice.ts
import {createSlice, PayloadAction} from '@reduxjs/toolkit';
import {RootState} from '../store';
// 初始状态类型
interface CounterState {
value: number;
}
// 定义一个初始状态
const initialState: CounterState = {
value: 0,
} as CounterState;
const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment: state => {
// Redux Toolkit 内置 Immer 库,可以直接修改 state
state.value += 1;
},
decrement: state => {
state.value -= 1;
},
incrementByAmount: (state, action: PayloadAction<number>) => {
state.value += action.payload;
},
},
});
// 每个 case reducer 函数会生成对应的 Action creators
export const {increment, decrement, incrementByAmount} = counterSlice.actions;
export default counterSlice.reducer;
将 slice 加入到 store
// src/store/store.ts
import {combineReducers, configureStore} from '@reduxjs/toolkit';
import counterSlice from './slices/counterSlice';
const rootReducer = combineReducers({
counter: counterSlice,
// 有新的 slice 就往这里加
});
export const store = configureStore({
reducer: rootReducer,
});
派发 action
先加入相关的 ts 类型:
// src/store/store.ts
// 省略其他代码
// 从 store 中推断出 `RootState` 和 `AppDispatch` 的类型
export type RootState = ReturnType<typeof store.getState>;
// 推断出类型: {counter: CounterState}
export type AppDispatch = typeof store.dispatch;
导出新的 hook:
// src/store/hooks.ts
import {useDispatch, useSelector} from 'react-redux';
import type {TypedUseSelectorHook} from 'react-redux';
import type {RootState, AppDispatch} from './store';
// 用下面的带类型的方法替换 `useDispatch` 和 `useSelector`
export const useAppDispatch: () => AppDispatch = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
调用:
// src/App.ts
import {Button, Text, View} from 'react-native';
import React from 'react';
import {decrement, increment} from '@store/slices/counterSlice';
import {useAppDispatch, useAppSelector} from '@store/hooks';
const App = () => {
const count = useAppSelector(state => state.counter.value);
const dispatch = useAppDispatch();
return (
<Provider store={store}>
<View>
<Button title="增加" onPress={() => dispatch(increment())} />
<Text>{count}</Text>
<Button title="减少" onPress={() => dispatch(decrement())} />
</View>
</Provider>
);
};
export default App;
处理异步 action
redux-tookit 有内置处理异步的中间件 createAsyncThunk:
// src/store/slice/counterSlice.ts
import {createAsyncThunk, createSlice, PayloadAction} from '@reduxjs/toolkit';
// 异步处理函数:
export const incrementDelay = createAsyncThunk(
'counter/incrementDelay',
async (payload: number) => {
return new Promise<number>(resolve => {
setTimeout(() => {
resolve(payload);
}, 1000);
});
},
);
const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment: state => {
// Redux Toolkit 内置 Immer 库,可以直接修改 state
state.value += 1;
},
decrement: state => {
state.value -= 1;
},
incrementByAmount: (state, action: PayloadAction<number>) => {
state.value += action.payload;
},
},
// 将异步函数回调加入slice
extraReducers: builder => {
builder
// incrementDelay fulfilled后会触发这个函数
.addCase(incrementDelay.fulfilled, (state, action) => {
state.value += action.payload;
})
// incrementDelay pending 触发
.addCase(incrementDelay.pending, (state, action) => {})
// incrementDelay rejected 触发
.addCase(incrementDelay.rejected, (state, action) => {});
},
});
调用异步 action:
// src/App.tsx
import {incrementDelay} from '@store/slices/counterSlice';
// 省略其他代码
<Button title="延迟增加1" onPress={() => dispatch(incrementDelay(1))} />
持久化数据
加入依赖:
yarn add redux-persist
yarn add @react-native-async-storage/async-storage
修改 store.ts:
// src/store/store.ts
import {combineReducers, configureStore} from '@reduxjs/toolkit';
import counterSlice from './slices/counterSlice';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {
persistStore,
persistReducer,
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER,
} from 'redux-persist';
// 持久化配置
const persistConfig = {
key: 'root',
version: 1, // 持久化数据版本
whitelist: ['counter'], // 需要持久化的 slice 名称
storage: AsyncStorage, // 使用 AsyncStorage 作为持久化存储的仓库
};
const rootReducer = combineReducers({
counter: counterSlice,
});
const persistedReducer = persistReducer(persistConfig, rootReducer);
export const store = configureStore({
reducer: persistedReducer, // 替换为持久化后的reducer
middleware: getDefaultMiddleware => {
const defaultMiddleware = getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
});
return defaultMiddleware;
},
});
export const persistor = persistStore(store);
修改 App.tsx:
// src/App.tsx
import React from 'react';
import {Provider} from 'react-redux';
import {persistor, store} from '@store/store';
import {PersistGate} from 'redux-persist/integration/react';
const App = () => {
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
...
</PersistGate>
</Provider>
);
};
export default App;
使用 Flipper 调试 redux
react-native 使用 Flipper 工具调试 redux 的时候需要装一个中间件。
加入依赖:
yarn add -D react-native-flipper
yarn add -D redux-flipper
加入中间件:
export const store = configureStore({
reducer: persistedReducer,
middleware: getDefaultMiddleware => {
const defaultMiddleware = getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
});
// 开发模式的时候加入中间件
if (__DEV__) {
const createDebugger = require('redux-flipper').default;
return defaultMiddleware.concat(createDebugger());
}
return defaultMiddleware;
},
});
然后在 Flipper 下载 redux 插件即可查看。
❤️ 支持
如果本文对你有帮助,点赞 👍 支持下我吧,你的「赞」是我创作的动力。