使用Redux處理異步問題
useSelector,useDispatch
首先,也是最重要的一點(diǎn)。如果你不知道要不要用redux,那么最好不要用。
redux主要解決的問題是統(tǒng)一來源的狀態(tài)管理。
- 全局state存放在store里。
store.getState()可以獲得state樹。 - 給store,發(fā)送action可以通過reducer生成新的state。
store.dispatch({type:SOME_ACTION, data: {})。 - 訂閱store,或者新的state。
store.subscribe(() => store.getState())。
React-redux主要解決的是第二條。使用connect方法把state和actions都作為props注入到了組件里。
比如現(xiàn)在有一個Counter組件。increment做為action creator。狀態(tài)就是value++。
那么可以寫成:
function Counter(props) {
// ...
return (<Button onClick={() => props.increment()}>+</Button>)
}
const mapStateToProps = (state) => ({
value: state.value,
});
const mapActionToProps = (dispatch) => ({
increment: dispatch(increment()),
})
connect(mapStateToProps, mapActionToProps)(Counter);
大概就是上面這樣的。使用了react-redux的hooks呢,畫風(fēng)一轉(zhuǎn)。整個顯得清晰了很多。當(dāng)然這里也不能少了redux toolkit的幫助。
要實(shí)現(xiàn)redux應(yīng)用的完全體就少不了要創(chuàng)建redux的store等這些前期的配置工作。為了減少這些繁瑣的配置,redux開發(fā)了toolkit這一套工具。項目代碼中都有,可以參考。這里不多介紹。
使用了react-redux之后看起來就是這樣了。我們在前期沒有多做action(action creator)和reducer的介紹。突然出現(xiàn)不能體現(xiàn)它的簡化后的好處。有一點(diǎn),action和reducer通常都放在不同的地方。使用起來不是十分方便。
在新的實(shí)現(xiàn)中這些都在slice文件中,方便統(tǒng)一的管理。維護(hù)起來也好很多。
import { createSlice } from '@reduxjs/toolkit';
export const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0,
},
reducers: {
increment: state => {
state.value += 1;
},
decrement: state => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
});
// Action creators are generated for each case reducer function
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
這是使用了redux toolkit的好處。action的部分基本不用處理。它會自動生成出來action creator。
react-redux的connect方法也省去了。
代替的方案是useSelector和useDispatch兩個方法。
在ReduxCounter組件里:
// ...
const ReduxCounter: React.FC<ReduxCounterProps> = props => {
// ...
const count = useSelector((state: RootState) => { // 1
return state.counter.value;
});
const dispatch = useDispatch(); // 2
const onAdd = () => dispatch(increment()); //3
return (
<View>
<Text>{count}</Text>
</View>
<View style={styles.buttonWrapper}>
<TouchableHighlight style={styles.button} onPress={onAdd}>
<View style={styles.buttonInsider}>
<Text>+</Text>
</View>
</TouchableHighlight>
);
};
export { ReduxCounter };
- 1. 使用
useSelector獲取state樹對應(yīng)到這個組件的狀態(tài) - 2. 使用
useDispatch獲取dispatch方法,可以發(fā)送action - 3. 在處理add點(diǎn)擊的時候調(diào)用dispatch方法發(fā)送
increment()action creator生成的action。
處理異步
在一般的開發(fā)中需要處理很多的網(wǎng)絡(luò)請求,緩存讀寫等情況。這些都是異步的。
Redux提供了兩種方法來處理異步的情況:
- createAsyncThunk
- RTK Query, redux toolkit query
下面主要通過異步緩存讀寫來演示如何使用這兩種方法。
在React Native里用來處理簡單的字符串存取的庫一般是
@react-native-async-storage/async-storage
import:
import AsyncStorage from '@react-native-async-storage/async-storage';
讀、寫,刪除:
// inside a async function
const ret = await AsyncStorage.getItem('@your-key');
await AsyncStorage.setItem('@your-key', xxx-xxx-xxx);
await AsyncStorage.removeItem('@your-key');
createAsyncThunk
很久以前,有一個用redux就用過的redux插件叫做redux-thunk。
現(xiàn)在我們有了createAsyncThunk。
在使用的時候和前文提到的slice的套路基本一致。首先我們來新建一個slice叫做authSlice。
在里面填空比如:name,initialState。
reducers為空對象,處理非異步的情況。
新增的是:
- 新建相關(guān)的thunk
extraReducers
新建thunk
const authenticate = createAsyncThunk<boolean, string, any>(
'users/auth',
async (token: string) => {
try {
await AsyncStorage.setItem(GITHUB_TOKEN_KEY, token);
return true;
} catch (e) {
console.error('ERROR:', e);
return false;
}
},
);
const authSlice = createSlice({
name: 'auth',
initialState: {
authed: false,
},
reducers: {},
});
添加extraReducers
異步的thunks就放在extraReducers里:
const authSlice = createSlice({
name: 'auth',
initialState: {
authed: false,
},
reducers: {},
extraReducers: builder => {
builder.addCase(authenticate.fulfilled, state => {
state.authed = true;
});
builder.addCase(removeToken.rejected, state => {
state.authed = false;
});
},
});
最后export出去:
export { authenticate, removeToken, authSlice };后續(xù)還要在store里綁定reducer。
export const store = configureStore({
reducer: { counter: counterSlice.reducer, auth: authSlice.reducer },
});
使用上和之前的countSlice一樣:
// 讀取state值const authed = useSelector((state: RootState) => state.auth.authed);
在TokenScreen.tsx文件里可以看到具體代碼。
發(fā)出thunk:
const dispatch = useAppDispatch(); // 1
try {
const ret = await dispatch(authenticate(text)).unwrap(); // 2
if (ret) {
console.log('>result action: ', 'DONE');
}
navigation.replace('Tabs');
} catch (e) {
// TODO: deal with the error
}
拿到useAppDispatch方法。在src/store.ts文件里。
本質(zhì)就是useDispatch。
處理分發(fā)的thunk的結(jié)果的時候可以用redux提供的unwrap方法直接得到結(jié)果。
在catch語句里處理錯誤。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
React應(yīng)用框架Dva數(shù)據(jù)流向原理總結(jié)分析
這篇文章主要為大家介紹了React 應(yīng)用框架Dva數(shù)據(jù)流向原理總結(jié)分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
webpack 2.x配置reactjs基本開發(fā)環(huán)境詳解
本篇文章主要介紹了webpack 2.x配置reactjs基本開發(fā)環(huán)境詳解,具有一定的參考價值,有興趣的可以了解一下2017-08-08
React+Ant Design開發(fā)環(huán)境搭建的實(shí)現(xiàn)步驟
這篇文章主要介紹了React+Ant Design開發(fā)環(huán)境搭建的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
實(shí)現(xiàn)React單頁應(yīng)用的方法詳解
今天我們來學(xué)習(xí)React是如何構(gòu)建起一個單頁應(yīng)用的,React作為目前最流行的前端框架之一,其受歡迎程度不容小覷,從這門框架上我們可以學(xué)到許多其他前端框架所缺失的東西,也是其創(chuàng)新性所在的地方,比如虛擬DOM、JSX等。下面一起來看看。2016-08-08
react項目初始化時解析url路徑中的動態(tài)片段實(shí)現(xiàn)方案
本文將深入探討React項目初始化階段如何高效解析URL路徑中的動態(tài)片段,實(shí)現(xiàn)優(yōu)雅的路由參數(shù)處理,幫助開發(fā)者構(gòu)建更靈活的應(yīng)用程序,感興趣的朋友一起看看吧2025-07-07

