1.安装
yarn add react-thunk
yarn add redux-promise
yarn add redux
yarn add react-redux
项目目录
2.定义两个reduce
count.ts
type InitStore = {
num: number
}
export type CountAction = {
type: string,
num: number
}
// store初始值
const initStore: InitStore = { num: 100 };
// 创建各个操作
第一个参数为初始值,第二个参数为操作
export const countReducer = (state = initStore, action: CountAction) => {
switch (action.type) {
case 'Add':
return {
...state,
num: state.num += action.num
};
case 'Decrement':
return {
...state,
num: state.num -= action.num
};
case 'Multi':
return {
...state,
num: state.num *= action.num
};
case 'Division':
return {
...state,
num: state.num /= action.num
};
default:
return state;
}
};
user.ts
type InitStore = {
user: string
isLogin: boolean
text: string
}
type UserAction = {
type: string,
isLogin: boolean,
text: string
}
// store初始值
const initStore: InitStore = {
user: 'admin',
isLogin: false,
text: '未登录'
};
// 创建各个操作
export const userReducer = (state = initStore, action: UserAction) => {
switch (action.type) {
case 'Login':
return {
...state,
isLogin: action.isLogin,
text: action.text
};
case 'Logout':
return {
...state,
isLogin: action.isLogin,
text: action.text
};
default:
return state;
}
};
3.定义所有的action
action.ts
const increment = {
type: 'Add',
num: 1
};
const decrement = {
type: 'Decrement',
num: 1
};
const multi = {
type: 'Multi',
num: 2
};
const division ={
type: 'Division',
num: 2
};
const login = {
type: 'Login',
isLogin: true,
text: '已登录'
};
const logout = {
type: 'Logout',
isLogin: false,
text: '未登录'
};
export {
increment,decrement,multi,division,login,logout
};
4.创建store
index.ts
import { createStore, combineReducers } from 'redux';
import { countReducer } from './count';
import { userReducer } from './user';
const reducer = combineReducers({
user: userReducer,
count: countReducer
});
export function userStore() {
return createStore(reducer);
}
5. store.subscribe()函数的使用
store.subscribe()
监听store数据的变化,只要数据发生变化那么这个函数就会执行
6.store与组件关联实现数据修改后刷新页面
- 将store传递给子代
index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import 'nprogress/nprogress.css';
import './style/index.css';
import {
BrowserRouter as Router,
} from 'react-router-dom';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { userStore } from './store';
import { Provider } from 'react-redux';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement,
);
root.render(
<Router>
<Provider store={userStore()}> //将store传递给子代
<App/>
</Provider>
</Router>
);
reportWebVitals();
- 子代获取store里面的操作
mapStateToProps
mapDispatchToProps
connect(mapStateToProps, mapDispatchToProps)(componentName)
//Test.tsx
import React, { useEffect } from 'react';
import { connect, MapStateToProps } from 'react-redux';
import { RootStore, userStore } from '../store';
import { login, decrement, increment, logout } from '../store/actions';
import { Dispatch } from 'redux';
type Props = {
store: RootStore
addN: (value: number) => { type: string, num: number }
}
const Test: React.FC<Props> = (props) => {
const { store, addN} = props;
return (
<>
<div>test</div>
<div>{store.count.num}</div>
<button onClick={()=>addN(50)}>+1</button>
</>
);
};
const mapStateToProps:MapStateToProps<any, any, any> = (state: RootStore) => {
return {
store:state
};
};
const mapDispatchToProps = (dispatch: Dispatch) => {
return {
addN: (value: number) => dispatch(increment(value)),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Test);
7.处理异步任务
引入中间件
import { createStore, combineReducers,applyMiddleware } from 'redux';
import { countReducer, InitCountStore } from './count';
import { InitUserStore, userReducer } from './user';
import thunk from 'redux-thunk'
export type RootStore= {
user:InitUserStore
count:InitCountStore
}
const reducer = combineReducers({
user: userReducer,
count: countReducer
});
export function userStore() {
return createStore(reducer,applyMiddleware(thunk)); //使用异步中间件
}
定义一个异步任务
const fuck = () => {
return new Promise((resolve, reject) => {
// axios.get<number>('/xxx')
// .then(res => {
// resolve({
// type: 'Reset',
// num: res
// });
// });
setTimeout(() => {
resolve({
type: 'Add',
num: 900
});
},3000);
});
};
将异步任务操作传给组件
const mapDispatchToProps = (dispatch: Dispatch) => {
return {
addN: (value: number) => dispatch(increment(value)),
subN: (value: number) => dispatch(decrement(value)),
signin:()=>dispatch(login),
signout:()=>dispatch(logout),
resetN:async ()=>dispatch((await fuck()) as AnyAction) //异步任务映射到props
};
};
组件调用
const Test: React.FC<Props> = (props) => {
const { store, addN,signin,signout,resetN} = props;
return (
<>
<div>test</div>
<div>{store.count.num}</div>
<div>{JSON.stringify(store.user)}</div>
<button onClick={()=>addN(50)}>+1</button>
<button onClick={()=>signin()}>+login</button>
<button onClick={()=>signout()}>+login</button>
<button onClick={()=>resetN()}>重置</button> //调用异步任务
</>
);
};
注意
另外redux
的书写很麻烦官方推荐使用 @reduxjs/toolkit
这个库