Hooks Redux

Top Level File

1
2
3
4
5
6
7
8
import { Provider } from 'react-redux';
import store from '<path of store file>';

export type RootState = ReturnType<typeof store.getState>;

<Provider store={store}>
<App />
</Provider>

Store File

1
2
3
4
5
6
7
8
9
import reduxSliceOne from '<redux slice file one>';
import reduxSliceTwo from '<redux slice file two>';

export default configureStore({
reducer: {
reduxOne: reduxSliceOne,
reduxTwo: reduxSliceTwo,
},
});

Redux Slice File One

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import { createSlice, PayloadAction, createAsyncThunk } from '@reduxjs/toolkit';

import { RootState } from '<path of top level file>';

type DataState = string; // What do u want

interface ReduxSliceOneState {
data: DataState,
status: 'idle' | 'loading' | 'succeeded' | 'failed',
error: string | null | undefined,
}

const initialState = {
data: 'Hey Man ~',
status: 'idle',
error: null,
} as ReduxSliceOneState;

interface fetchParams {
id: number,
age: number,
}

// Async Update
const fetchReduxOneData = createAsyncThunk(
'redux/one', // What do u want
async (params: fetchParams) => {

// Just for example

await fetch(params);

// Or:
// return new Promise<DataState>((resolve, rejects) => {
// const client = new Client('<url>');

// client.on('error', async (err) => {
// rejects(err);
// });
// client.on('close', () => {});

// client.on("open", async () => {
// try {
// const data = await client.fetch(params);
// resolve(data);
// } catch (err) {
// rejects(err)
// } finally {
// client.close();
// }
// });
// });
}
);

const slice = createSlice({
name: 'reduxOne',
initialState: initialState,
reducers: {
// Sync Update
updateData(state, action: PayloadAction<DataState>) {
state.data = action.payload;
},
},
extraReducers: builder => {
builder.addCase(fetchReduxOneData.pending, (state) => {
state.status = 'loading';
});
builder.addCase(fetchReduxOneData.rejected, (state, action) => {
state.status = 'failed';
state.error = action.error.message || 'Something Error ...';
});
builder.addCase(fetchReduxOneData.fulfilled, (state, action) => {
state.status = 'succeeded';
state.data = action.payload;
});
},
});

export { fetchReduxOneData };
export const { updateData } = slice.actions;
export const selectReduxOneData = (state: RootState) => state.reduxOne; // Related: store

export default slice.reducer;

Companent

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import { FC, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchReduxOneData, updateData, selectReduxOneData } from '<redux slice file one>'

const Home: FC = () => {
const dispatch = useDispatch();
const reduxOneData = useSelector(selectReduxOneData);

useEffect(() => {
if (reduxOneData.status==='failed') {
alert(reduxOneData.error);
}
}, [reduxOneData]);

const handleClickUpdate = () => {
dispatch(updateData('Hey Man Too ~'));
}

const handleClickUpdateAsync = () => {
dispatch(fetchReduxOneData({ id: 1, age: 2 }));
}

return (
<div>
{reduxOneData.status === 'loading' ? 'loading ...' : reduxOneData.data}
<button onClick={handleClickUpdate}>Update</button>
<button onClick={handleClickUpdateAsync}>Async Update</button>
</div>
)
};

export default App;
打赏
  • © 2016-2021 留叶
  • Powered by Hexo Theme Ayer
    • PV:
    • UV:

请我喝杯咖啡吧~

支付宝
微信