Redux - Async Thunks
Async logic (like fetching data) should live in thunks. Redux Toolkit’s createAsyncThunk
simplifies loading and error handling.
Try it: Simulated fetch
View source
const { createSlice, configureStore, createAsyncThunk } = RTK;
const fetchGreeting = createAsyncThunk('greet/fetch', async () => {
await new Promise(r => setTimeout(r, 500));
if (Math.random() < 0.1) throw new Error('Random failure');
return { message: 'Hello from thunk!' };
});
const slice = createSlice({
name: 'greet',
initialState: { status: 'idle', data: null, error: null },
reducers: {},
extraReducers: b => {
b.addCase(fetchGreeting.pending, (s) => { s.status='loading'; s.error=null; })
.addCase(fetchGreeting.fulfilled, (s, a) => { s.status='succeeded'; s.data=a.payload; })
.addCase(fetchGreeting.rejected, (s, a) => { s.status='failed'; s.error=a.error.message; });
}
});
const store = configureStore({ reducer: { greet: slice.reducer } });
function App(){
const { Provider, useSelector, useDispatch } = ReactRedux;
function Panel(){
const st = useSelector(s => s.greet);
const dispatch = useDispatch();
return (
<div>
<button onClick={() => dispatch(fetchGreeting())} disabled={st.status==='loading'}>Fetch</button>
<div style={{marginTop:8}}>Status: {st.status}</div>
{st.data && <div>Data: {st.data.message}</div>}
{st.error && <div style={{color:'salmon'}}>Error: {st.error}</div>}
</div>
);
}
return <Provider store={store}><Panel /></Provider>;
}
ReactDOM.createRoot(document.getElementById('thunk-root')).render(<App />);
Syntax primer
createAsyncThunk(type, payloadCreator)
emits pending/fulfilled/rejected actions.- Handle those in
extraReducers
to setstatus
,data
, anderror
.