
Action 就是一个普通 JavaScript 对象(注意到没,这儿没有任何魔法?)用来描述发生了什么。reducer。再次地强调,没有任何魔法,reducer 只是一个接收 state 和 action,并返回新的 state 的函数,并且是一个纯函数。store 中。store.dispatch() 将 action 传到 store。getState() 方法获取 state;dispatch(action) 方法更新 state;subscribe(listener) 注册监听器;subscribe(listener) 返回的函数注销监听器。npm install --save redux

import { createStore } from 'redux';
/**
* 这是一个 reducer,形式为 (state, action) => state 的纯函数。
* 描述了 action 如何把 state 转变成下一个 state。
*
* state 的形式取决于你,可以是基本类型、数组、对象、
* 甚至是 Immutable.js 生成的数据结构。惟一的要点是
* 当 state 变化时需要返回全新的对象,而不是修改传入的参数。
*
* 下面例子使用 `switch` 语句和字符串来做判断,但你可以写帮助类(helper)
* 根据不同的约定(如方法映射)来判断,只要适用你的项目即可。
*/
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
// 创建 Redux store 来存放应用的状态。
// API 是 { subscribe, dispatch, getState }。
let store = createStore(counter);
// 可以手动订阅更新,也可以事件绑定到视图层。
store.subscribe(() =>
console.log(store.getState())
);
// 改变内部 state 惟一方法是 dispatch 一个 action。
// action 可以被序列化,用日记记录和储存下来,后期还可以以回放的方式执行
store.dispatch({ type: 'INCREMENT' });// 1
store.dispatch({ type: 'INCREMENT' });// 2
store.dispatch({ type: 'DECREMENT' });// 1

因为上面的简单例子中的state没有在页面上渲染,所以简单优化一下,实现页面渲染操作,想呈现的效果如下:

如果用纯react写的话,很简单,代码如下:
import { useState } from "react";
function CountNum(){
const [count,setCount] = useState(0);
function add(){
setCount(count => count+1);
}
function subtract(){
setCount(count => count-1);
}
return(
<div>
当前数字是:{count}
<br /><br />
<button onClick={add}>点我 +1</button> <br /><br />
<button onClick={subtract}>点我 -1</button>
</div>
)
}
export default CountNum;
但我们目的是用redux实现,所以继续……




使用 useEffect 进行重新渲染,核心代码如下:
useEffect(()=>{
store.subscribe(()=>{
console.log('订阅更新,打印2-----',store.getState());
setCount(store.getState());
});
});

然后再看效果:

关于useEffect ,可以看下面的文章:
React中组件通信02——消息订阅与发布、取消订阅以及卸载组件时取消订阅.
countReducer.js
/**
* 这是一个 reducer,形式为 (state, action) => state 的纯函数。
* 描述了 action 如何把 state 转变成下一个 state。
*
* state 的形式取决于你,可以是基本类型、数组、对象、
* 甚至是 Immutable.js 生成的数据结构。惟一的要点是
* 当 state 变化时需要返回全新的对象,而不是修改传入的参数。
*
* 下面例子使用 `switch` 语句和字符串来做判断,但你可以写帮助类(helper)
* 根据不同的约定(如方法映射)来判断,只要适用你的项目即可。
*/
function countReducer(state = 0,action){
console.log(`state:${state}---action:${action}---type:${action.type}`);
switch (action.type){
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
export default countReducer;
store.js
import { createStore } from 'redux';
import countReducer from './countReducer.js'
const store = createStore(countReducer);
export default store;
CountNumRedux.jsx
import { useState,useEffect } from "react";
import store from '../redux/store'
function CountNumRedux(){
const [count,setCount] = useState(0);
function add(){
// setCount(count => count+1);
//派发action 改变内部 state 惟一方法是 dispatch 一个 action。
store.dispatch({ type: 'INCREMENT' });
}
function subtract(){
// setCount(count => count-1);
store.dispatch({ type: 'DECREMENT' });
}
// 可以手动订阅更新,也可以事件绑定到视图层。
// store.subscribe(() =>
// console.log('订阅更新,打印1-----',store.getState())
// );
useEffect(()=>{
store.subscribe(()=>{
console.log('订阅更新,打印2-----',store.getState());
setCount(store.getState());
});
});
return(
<div>
当前数字是:{count}
当前数字是:{store.getState()}
<br /><br />
<button onClick={add}>点我 +1</button> <br /><br />
<button onClick={subtract}>点我 -1</button>
</div>
)
}
export default CountNumRedux;
{
type: ADD_TODO,
text: 'Build my first Redux app'
}
{
type: TOGGLE_TODO,
index: 5
}





代码在上面基础上做了简单的调整,action的type抽出了变量,直接给代码了,如下:
countConst.js
//定义常量
export const INCREMENT = 'INCREMENT'; //加
export const DECREMENT = 'DECREMENT'; //减
countAction.js
// //加的时候
// function incrementNum(){
// return { type: 'INCREMENT' };
// }
// //减的时候
// function decrementNum(){
// return { type: 'DECREMENT' };
// }
import {INCREMENT,DECREMENT} from './countConst.js'
//加的时候
function incrementNum(number){
return { type: INCREMENT,number:number };
}
//减的时候
function decrementNum(number){
return { type: DECREMENT,number:number };
}
export default{incrementNum,decrementNum}
CountNumRedux.jsx
import { useState,useEffect,useRef, createRef } from "react";
import store from '../redux/store'
import countAction from '../redux/countAction'
function CountNumRedux(){
const [count,setCount] = useState(0);
const numberRef = createRef();
function add(){
// setCount(count => count+1);
//派发action 改变内部 state 惟一方法是 dispatch 一个 action。
// store.dispatch({ type: 'INCREMENT' });
// store.dispatch(countAction.incrementNum());
// console.log(numberRef.current.value);
let number = numberRef.current.value;
// console.log(typeof number); //string
store.dispatch(countAction.incrementNum(parseInt(number)));
}
function subtract(){
let number = parseInt(numberRef.current.value);
store.dispatch(countAction.decrementNum(number));
}
useEffect(()=>{
store.subscribe(()=>{
console.log('订阅更新,打印2-----',store.getState());
setCount(store.getState());
});
});
return(
<div>
当前数字是:{count}
当前数字是:{store.getState()}
<br />
浮动数字:<input type="number" ref={numberRef}/>
<br /><br />
<button onClick={add}>点我 加数</button> <br /><br />
<button onClick={subtract}>点我 减数</button>
</div>
)
}
export default CountNumRedux;
countReducer.js
import {INCREMENT,DECREMENT} from './countConst.js'
function countReducer(state = 0,action){
console.log(`state:${state}---action:${action}---type:${action.type}---number${action.number}`);
switch (action.type){
case INCREMENT:
// return state + 1;
return state + action.number;
case DECREMENT:
// return state - 1;
return state - action.number;
default:
return state;
}
}
export default countReducer;