React-Redux

React-Redux is different from Redux which is build from React, while Redux is a plugin and you can use it in Vue also.

在index js 中设置provider 传递store给App下所有子组件

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import store from './components/redux/store.jsx'
import {Provider} from 'react-redux'

ReactDOM.render(
	<Provider store={store}>
		<App/>
	</Provider>,
	document.getElementById('root')
)

在components下建containers和redux文件如下,也可把reducer再汇总成一个,只暴露index-reducer

redux

在store中引入reducer,使用中间件

//引入createStore,专门用于创建redux中最为核心的store对象
import {createStore,applyMiddleware,combineReducers} from 'redux'

//引入reducer
import addReducer from './reducers/add-reducer'
import personReducer from './reducers/person-reducer'

//引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk'

const allReducers = combineReducers({
	adds:addReducer,
	persons:personReducer
})

//暴露store
export default createStore(allReducers,applyMiddleware(thunk))

在action中 pass type and data to reducer

export const createAddPersonAction =(personObj)=>({type:'addPerson',data:personObj})
export function createIncrementAction(data){
    return {type:'increment',data}
}

export const createDecrementAction = data =>({type:'decrement',data})

export const createIncrementAsyncAction = (data,syncTime)=> {
    return (dispatch)=>{
		setTimeout(()=>{
			dispatch(createIncrementAction(data))
		},syncTime)
	}
}

在reducer接收previous value 和action,action中有type和打他,再加工数据

const init = [{id:'001',name:'zhang',age:10}]
export default function personReducer(pre,action){
    const {type,data} = action
    switch (type) {
        case 'addPerson' :
            return [data,...pre]
            //return pre.unshift(data) not working 
        default:
            return init
    }
}

在 container里通过connect中state接到数据,再通过props传递给UI

In Person.jsx container

import React, { Component } from 'react'
import {connect} from 'react-redux'
import {createAddPersonAction} from '../redux/actions/person-action'
class Person extends Component {
    addPerson=()=>{
        const name = this.nameNode.value
        const age = this.ageNode.value
        const personObj = {id:Date.now(),name,age}
        this.props.addPersons(personObj)
    }
    render() {
        return (
            <div>
                <h1>Up: {this.props.sum}</h1>
                <input ref={c=>{this.nameNode = c}} type="text" placeholder='name' />
                <input ref={c=>{this.ageNode=c}} type="text" placeholder='age' />
                <button onClick={this.addPerson}>add</button>
                <ul>
                   {this.props.people.map(p=>{
                       return <li key={p.id}>
                           {p.name} --- {p.age}
                       </li>
                   })}
                </ul>
            </div>
        )
    }
}
export default connect(
    state =>({people:state.persons,sum:state.adds}),{
        addPersons:createAddPersonAction
    }
)(Person)

In Add.jsx container

import React, { Component } from 'react'
import {connect} from 'react-redux'
import { createIncrementAction,createDecrementAction,createIncrementAsyncAction} from '../redux/actions/add-action'
class Add extends Component {

    increment=()=>{
        const{value} = this.selectNum
        this.props.add(value*1)
    }
    decrement=()=>{      
        const{value} = this.selectNum
        this.props.minus(value*1)
     }
     incrementAsync=()=>{
        const {value} = this.selectNum
        this.props.addAsync(value*1,500)
     }
    
    render() {
        return (
            <div>
                <h1>Total is {this.props.total}</h1>
                <h1>Up is {this.props.people.length}</h1>
                <select ref={c=>{this.selectNum=c}}>
                    <option value='1'>1</option>
                    <option value="2">2</option>
                    <option value="3">3</option>
                </select>
                <button onClick={this.increment}>add</button>
                <button onClick={this.decrement}>minuse</button>
                <button onClick={this.incrementAsync}>asyncronus add</button>
            </div>
        )
    }

}
export default connect(
        state => ({total:state.adds,people:state.persons}),
        {
            add:createIncrementAction,
            minus:createDecrementAction,
            addAsync:createIncrementAsyncAction
        }
    )(Add)