在没有使用react-redux时
store实例有一个私有变量_state
state = store.getState()得到的是_state经过序列化在变成json对象,JSON.parse(JSON.stringify(this._state));
因此state和_state内容相同,但是修改state不会影响_state,事实上_state = reducer(state,action),
当执行store.dispatch(action)时,有两个步骤:第一,修改私有_state,_state = reducer(state,action),
第二,store.subscribe(fn)在监听_state的状态,只要store.dispatch(action)执行,不管_state是否发生变化,fn函数都会执行
[javascript] view plain copy
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, bindActionCreators } from 'redux';
function reducer(state,action){
if (typeof state === 'undefined') return {name:'Jack',num:0};
switch (action.type){
case "changeName":
return Object.assign({},state,action.payload);
case "add":
return Object.assign({},state,{num: ++state.num});
default: return state;
}
}
const store = createStore(reducer);
let actions = {
changeName(name){
return{
type:'changeName',
payload:{name:name}
}
},
add(){
return{
type:'add'
}
}
}
actions = bindActionCreators(actions,store.dispatch)
class UI extends React.Component{
render(){
return(
<p>
<p>{this.props.name}</p>
<p>{this.props.num}</p>
<input onChange = {event => this.props.changeName(event.target.value)} />
<button onClick = {event => this.props.add()}>add</button>
</p>
)
}
}
function render(){
let state = store.getState();
ReactDOM.render(<UI changeName = {actions.changeName} add = {actions.add} name= {state.name} num = {state.num}/>,
document.getElementById('test'))
}
store.subscribe(render);
render();
使用react-redux时
本质就是Object.assign(this.props,store.getState(),actions); store.subscribe(ReactDOM.render())
function getState(state){
return state;
}
参数state就是store.getState(),store是由<Provider store={store}><UI/></Provider>中的store提供的。
function getActions(){
return actions;
}
函数getActions()没有参数。
[javascript] view plain copy
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, bindActionCreators } from 'redux';
import {connect,Provider} from 'react-redux';
function reducer(state,action){
if (typeof state === 'undefined') return {name:'Jack',num:0};
switch (action.type){
case "changeName":
return Object.assign({},state,action.payload);
case "add":
return Object.assign({},state,{num: 1+state.num});
default: return state;
}
}
const store = createStore(reducer);
let actions = {
changeName(name){
return{
type:'changeName',
payload:{name:name}
}
},
add(){
return{
type:'add'
}
}
}
actions = bindActionCreators(actions,store.dispatch)
class UI extends React.Component{
render(){
return(
<p>
<p>{this.props.name}</p>
<p>{this.props.num}</p>
<input onChange = {event => this.props.changeName(event.target.value)} />
<button onClick = {event => this.props.add()}>add</button>
</p>
)
}
}
function getState(state){
return state;
}
function getActions(){
return actions;
}
UI = connect(getState,getActions)(UI);
ReactDOM.render(<Provider store={store}><UI/></Provider>,
document.getElementById('test'));
上面的代码可以将
actions = bindActionCreators(actions,store.dispatch);
function getActions(){return actions;}
这两条语句去掉
再将UI = connect(getState,getActions)(UI);修改成UI = connect(getState,actions)(UI);
因为当actions是json对象时,函数内部会自动调用bindActionCreators(actions,store.dispatch);
function getState(state,props){
return state;
}
当没有第二个参数props时,只会输出一次123
当有第二个参数props时,输出两次123
[javascript] view plain copy
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, bindActionCreators } from 'redux';
import {connect,Provider} from 'react-redux';
function reducer(state,action){
if (typeof state === 'undefined') return {name:'Jack',num:0};
switch (action.type){
case "changeName":
return Object.assign({},state,action.payload);
case "add":
return Object.assign({},state,{num: 1+state.num});
default: return state;
}
}
const store = createStore(reducer);
let actions = {
changeName(name){
return{
type:'changeName',
payload:{name:name}
}
},
add(){
return{
type:'add'
}
}
}
class UI extends React.Component{
render(){
return(
<p>
<p>{this.props.name}</p>
<p>{this.props.num}</p>
<input onChange = {event => this.props.changeName(event.target.value)} />
<button onClick = {event => this.props.add()}>add</button>
</p>
)
}
}
function getState(state,props){
console.log(123);
return state;
}
UI = connect(getState,actions)(UI);
function render(name){
ReactDOM.render(<Provider store={store}><UI name={name}/></Provider>,
document.getElementById('test'));
}
render('Jack');
setTimeout(function(){
render('Mike')
},3000)
也可以将映射分开:
[javascript] view plain copy
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, bindActionCreators } from 'redux';
import {connect,Provider} from 'react-redux';
function reducer(state,action){
if (typeof state === 'undefined') return {name:'Jack',num:0};
switch (action.type){
case "changeName":
return Object.assign({},state,action.payload);
case "add":
return Object.assign({},state,{num: 1+state.num});
default: return state;
}
}
const store = createStore(reducer);
let actions = {
changeName(name){
return{
type:'changeName',
payload:{name:name}
}
},
add(){
return{
type:'add'
}
}
}
class OPT extends React.Component{
render(){
return(
<p>
<input onChange = {event => this.props.changeName(event.target.value)} />
<button onClick = {event => this.props.add()}>add</button>
</p>
)
}
}
OPT = connect(null,actions)(OPT);
class UI extends React.Component{
render(){
return(
<p>
<p>{this.props.name}</p>
<p>{this.props.num}</p>
<OPT/>
</p>
)
}
}
function getState(state){
return state;
}
UI = connect(getState)(UI);
ReactDOM.render(<Provider store={store}><UI name={name}/></Provider>,
document.getElementById('test'));