安装
npm install redux react-redux -S
- redux 这个包是在 action.js store.js reducer.js 中使用的;
- react-redux 这个包是在 react 的组件中使用的;
Redux 概念
- store 对象:这个 store 类似于 vuex 中的全局 new Vuex 对象,负责连接 action 和 reducer,是一个核心;
- action 对象:类似于 vuex 中的 mutation 和 action 的集合,它既支持同步操作数据,也支持异步操作数据,主要作用就是 通过 dispatch 提交 action,触发 修改 state 数据的行为;
- reducer 对象:类似于 vuex 中 state 属性,负责初始化 state 数据以及更新 state 数据;
Redux 用法
-
在 ./src/store.js 文件中创建 redux 的 store 对象,用于管理 action 和 reducer
import { createStore } from "redux"; // 导入 reducer import reducer from "./reducer"; // 在创建 store 对象的时候,要进行 state 的初始化操作,因此,createStore() 函数中必须要绑定 reducer,也就是让 reducer 和 store 产生关联,这样如果后期有 action 产生的时候,store 就会将这个 action 对象,转发给 reducer。 let store = createStore(reducer); // 暴露这个store对象 export default store;
-
由于 store 对象初始化的时候,要同时进行 state 的初始化,因此,在 ./src/reducer.js 文件中定义出来想要保存到 redux 中的 state。
import { combineReducers } from "redux"; // name是一个 reducer 对象,age 也是一个 reducer 对象 function name(state = "", action) { // 暂时用不到 修改state return state; } function age(state = 0, action) { return state; } // combineReducers() 可以将多个 reducer 对象合并成一个 reducer 对象,因为 createStore() 中只能设置一个 reducer export default combineReducers({ name, age, });
-
在 根组件 index.js 文件中,绑定 store,让组件和 redux 进行绑定。、
// 让 redux 中的 store 对象 和 react 中的组件产生关联; import { Provider } from "react-redux"; // 导入 创建好的 store 对象 import store from "./store/store"; ReactDOM.render( <Provider store={store}> <BrowserRouter> <App /> </BrowserRouter> </Provider>, document.getElementById("root") );
-
可以在任何一个组件中,去使用 redux 中的数据了。
import { connect } from "react-redux"; // connect()(Home) 该方法并不会修改原有组件 Home 的内容,仅仅是在 Home 组件的基础上包装上了 Redux 的内容 // connect(参数1,参数2):这两个参数都是函数,并且connect在执行函数回调的时候,会传递两个参数进来,一个参数就是state,这个state内,存储的就是 reducer.js 中声明的 数据(name,age)。 export default connect( (state) => { return { myName: state.name, // 相当于在当前 Home 组件中映射一个属性叫 myName,当前组件就可以使用 myName myAge: state.age, // 相当于在当前 Home 组件中映射一个属性叫 myAge,当前组件就可以使用 myAge }; }, (dispatch) => { return {}; } )(Home);
注意:组件中映射的 myName 和 myAge 属性,都被放在了 当前组件的 props 中。
-
如何通过 派发 action ,修改 state 的数据
action.js 文件中定义 各种 action
// 定义 修改name 的action function setName(value) { return { type: "SET_NAME", value, }; } // 定义 修改age 的action function setAge() { return { type: "SET_AGE", }; } export { setName, setAge };
在组件中映射 action 到当前组件
(dispatch) => { return { // 目的:在当前组件中映射一个方法,方法名称是 customChangeName。 customChangeName(name) { dispatch(setName(name)); // 派发action,交给 store,store 对象会将 这个 action,传递到 reducer 中进行全局匹配,看哪一个 reducer 能够匹配这个action }, }; }
总结:用户 派发 action -> store 转发 action 到 reducer(不需要我们处理) -> reducer 根据 action 更新 state,并返回最新的 state -> store 将最新的 state 返回到组件的 props 中(不需要我们做) -> props 变化导致组件被渲染,更新页面。
-
异步 Action
- 安装包 npm install redux-thunk
- 修改 store.js 文件,让 store 能够使用这个 thunk 中间件处理异步请求
import { createStore, applyMiddleware } from "redux"; import thunk from "redux-thunk"; // 一个处理异步 action 的包 // applyMiddleware(thunk): 让 store 对象使用中间件 thunk 来处理 action let store = createStore(reducer, applyMiddleware(thunk));
- 在 action.js 中定义异步 action
function saveUsers(list) { return { type: "SAVE_USERS", list, }; } // 带有异步请求的 action:使用场景 多个组件都要向这个接口发请求,并且都要使用请求过来的数据。 function queryUsers() { return (dispatch) => { axios.get("http://localhost:4000/users").then((res) => { // 请求成功的数据,要保存redux中 // 通过派发 action ,让 store 去找相应的 reducer。 dispatch(saveUsers(res.data)); }); }; }
- 在组件中,映射 reducer 和 异步请求的 action
(dispatch) => { return { // 目的:在当前组件中映射一个方法,方法名称是 customChangeName。 customChangeName(name) { dispatch(setName(name)); // 派发action,交给 store,store 对象会将 这个 action,传递到 reducer 中进行全局匹配,看哪一个 reducer 能够匹配这个action }, queryUsers() { dispatch(queryUsers()); }, }; }