是把数据从应用传到 store 的有效载荷。它是 store 数据的唯一来源。一般来说,就是通过 store.dispatch() 将 action 传到 store。
action 本质上是 JavaScript 普通对象。我们约定,action 内使用一个字符串类型的 type 字段来表示将要执行的动作。多数情况下,type 会被定义成字符串常量。当应用规模越来越大时,建议使用单独的模块或文件来存放 action。
action:{type:‘TODO’,payload:{name:‘lisi’}}
// action 类型
const ADD_TODO = 'ADD_TODO';
// 通过dispatch将action递交到reducer中处理
dispatch({
type: ADD_TODO,
payload:{name:'lisi'}
})
在具体使用过程中,通常会使用一个函数来生成相应的action对象,使得代码更容易测试和移植
// 生成action
function addTodo(text) {
return {
type: ADD_TODO,
text
};
}
// 通过dispatch将action递交到reducer中处理
dispatch(addTodo(text));
action 只是描述了有事情发生了这一事实,并没有指明应用如何更新 state。那么该如何去更新state或执行其他动作,这就是reducer需要关注的事情了。
通常一个reducer里存在一个switch,根据action类型来执行不同的state更新操作,同时包涵一个initState,用来初始化当前reducer中的state,其中返回的对象将会覆盖整个state对象,如果不希望变动其他对象,则需要对之前的state进行扩展赋值,只将更新的state进行覆盖
reducer(preSttate,action)
import { QUERY, SUBMIT } from "../actions/homeActions";
// 初始state
const initState = {};
// reducer 函数 reducer(preSttate,action)
const home = (state = initState, { type, payload }) => {
switch (type) {
case QUERY:
return { ...state, loading: false, ...payload };
case SUBMIT:
return { ...state, loading: false, ...payload };
default:
return { ...state, loading: true };
}
};
export default home;
使用 action 来描述“发生了什么”、使用 reducer 来根据 action 更新 state ,那么store就是负责将它们联系到一起的对象。
store的职责:
Redux 应用只有一个单一的 store!Redux 应用只有一个单一的 store!Redux 应用只有一个单一的 store!
当需要拆分处理数据的逻辑时,使用 reducer 组合(combineReducers()) 而不是创建多个 store。
import { createStore } from "redux";
// 多个reducers处理后的结果
import reducers from "../reducers";
// store通过createStore获取,Redux 应用只有一个单一的 store!
const store = createStore(reducers);
export default store;
综上,一个完整的redux应当包含actions、reducers、store三个部分。
使用Provider组件即可让整个dom树中的节点都能够通过connect去访问store的内容
import React from "react";
import ReactDOM from "react-dom";
import "./global.less";
import App from "./Route";
// 引入Provider
import { Provider } from "react-redux";
import store from "./redux/store";
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
import React, { Component } from "react";
import { connect } from "react-redux";
// 如需使用装饰器模式配置@babel/plugin-proposal-decorators
@connect(({ home }) => {
return { home };
})
class BaseLayout extends Component {
componentDidMount() {
// 可使用dispatch去更新store
console.log(this.props); // {children,dispatch,home}
}
render() {
const { children } = this.props;
return (
<div>
{children}
</div>
);
}
}
export default BaseLayout;
// BaseLayout.js
import React, { Component } from "react";
import { connect } from "react-redux";
import { updateStore } from "../../redux/actions/homeActions";
@connect(({ home }) => {
return { home };
})
class BaseLayout extends Component {
componentDidMount() {
console.log(this.props);
}
render() {
const { children, dispatch, home } = this.props;
return (
<div>
<button
onClick={() => {
// 按钮点击后将会把home的state更为{name:'张三'},updateStore为生成action的函数
dispatch(updateStore({ name: "张三" }));
}}
>
更新store
</button>
{home.name}
{children}
</div>
);
}
}
export default BaseLayout;
// homeActions.js (action)
export const QUERY = "QUERY";
export const SUBMIT = "SUBMIT";
export const updateStore = payload => {
return {
type: QUERY,
payload
};
};
// home.js (reducer)
import { QUERY, SUBMIT } from "../actions/homeActions";
const initState = {};
const home = (state = initState, { type, payload }) => {
switch (type) {
case QUERY:
return { ...state, loading: false, ...payload };
case SUBMIT:
return { ...state, loading: false, ...payload };
default:
return { ...state, loading: true };
}
};
export default home;