React状态管理之react-redux

614 阅读3分钟

react-redux

概念

Redux本身和React没有关系,是React-Redux让他们联系在一起。

安装

yarn add react-redux

UI组件和容器组件

React-Redux将所有组件分成两大类,UI组件和容器组件。
UI组件只负责UI的呈现,容器组件负责管理数据和逻辑。
如果一个组件既有UI又有业务逻辑,就需要将它进行拆分,外面是一个容器组件,里面包含一个UI组件。前者负责与外部的通信,将数据传递给后者,由后者进行渲染。

React-Redux规定,所有的UI组件都有用户提供,而容器组件则是由React-Redux生成。

Provider组件

React-Redux提供Provider组件,可以让容器组件拿到store。
使用方法如下:

import React from 'react';
import ReactDOM from 'react-dom';
import TodoList from './TodoList';
import { Provider } from 'react-redux'
import store  from './store'
const App = (
    <Provider store ={ store }>
        <TodoList />
    </Provider>
)
// Provider  位于<Provider /> 中的组件 都有能力获取到store中的数据
ReactDOM.render(App, document.getElementById('root'));

Connect方法

React-Redux提供connect方法,用于从UI组件生成容器组件。

import { connect } from 'react-redux'

const TodoList = connect(null,null)(TodoListUI)

connect 需要两个参数,用于定义业务逻辑。

参数1 mapStateToProps

字面上的意思是将state,映射为props。即将store中的state映射成UI组件的props,即 组件可以通过this.props获取到store中的state。
这表示输入的逻辑,表示外部的数据如何转换为UI组件的参数props

const mapStateToProps = (state) =>(
  {
  	inputValue: state.inputValue
  }
)

// mapStateToProps 是一个函数,默认会接收store中的state作为函数参数
// mapStateToProps 必须返回一个对象,表示映射规则
// 这里表示 将state.inputValue 映射成 inputValue
// 即在UI组件中,可以使用this.props.inputValue 获取store中的inputValue

参数2 mapDispatchToProps

字面上意义上,是将dispatch方法映射到props上,即将store.dispatch方法映射到组件的props上。
这表示输出逻辑,表示用户发出的动作如何变成action对象,并且从UI组件发送出去。

const mapDispatchToProps = (dispatch) => (
  {
  handleInputChange:(e)=>{
  	const action ={
    		type:'input_value_change',
      	value:e.target.value
    	}
    dispatch(action)
  	}
  }
)
	
// mapDispatchToProps是一个函数 默认接收store.dispatch方法作为参数
// mapDispatchToProps 必须返回一个对象,里面每一个键值对都是一个映射,表示UI组件的
// 参数应该怎么派发action

实例:TodoList

项目目录

image.png

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import TodoList from './TodoList';
import { Provider } from 'react-redux'
import store  from './store'
const App = (
    <Provider store ={ store}>
        <TodoList />
    </Provider>
)
// Provider  位于<Provider /> 中的组件 都有能力获取到store中的数据
ReactDOM.render(App, document.getElementById('root'));


TodoList.js

import React,{ Component } from 'react'

import { connect } from 'react-redux'
 class TodoList extends Component{
    // constructor(props){
    //     super(props)
    //     this.state = store.getState()

    // }
    
    render(){
        return(
            <div>
                <input type ="text"  value = {this.props.inputValue}  onChange ={ this.props.handleInputChange}/>
                <button onClick ={ this.props.handleBtnClick}>提交</button>
                <ul>
                    {
                        this.props.list.map((item,index)=>{
                            return <li key={index}>{item}</li>
                        })
                    }
                </ul>
            </div>
        )
    }
}
// 连接store  
const mapStateToProps = (state) => {
    // 固定接收store中的state作为参数
    // 返回一个对象
    return {
        // 把store中的state映射成组件的props
        //映射的规则  
        inputValue:state.inputValue,
        list: state.list
    }
}
const mapDispatchToProps = (dispatch) =>{
    // 如果想对store的数据进行修改
    // 接受dispatch方法  
    // store.dispatch
    // 把store.dispatch挂载到props上
    return {
        // handleInputChange = e => {
        //     console.log(e.target.value)
        //     // 修改store中的数据
        //     const action ={
        //         type:'input_value_change',
        //         value:e.target.value
        //     }
        //     dispatch(action)
    
        // },
        handleInputChange(e) {
            console.log(e.target.value)
            // 修改store中的数据
            const action ={
                type:'input_value_change',
                value:e.target.value
            }
            dispatch(action)
        },
        // handleBtnClick = ()=>{
        //     console.log("添加item")
        //     const action ={
        //         type:'add_list_item'
        //     }
        //     dispatch(action)
        // }
        handleBtnClick(){
            
                console.log("添加item")
                const action ={
                    type:'add_list_item'
                }
                dispatch(action)
            
        }
    }
}
//  conner是 连接组件和store   怎么连接  就是mapStateToProps   
export default connect(mapStateToProps,mapDispatchToProps)(TodoList)

store/index.js

import { createStore } from 'redux'
import reducer from './reducer'
const store = createStore(reducer)
export default store

store/reducer.js


const defaultState = {
    inputValue:'',
    list:[]
}
export default (state = defaultState,action)=>{
    if(action.type === 'input_value_change') {
        const newState = JSON.parse(JSON.stringify(state))
        console.log(action.value)
        newState.inputValue = action.value
        console.log(newState.inputValue)
        return newState
    }
    if( action.type === 'add_list_item') {
        const newState = JSON.parse(JSON.stringify(state))
        newState.list.push(newState.inputValue)
        newState.inputValue =''
        return newState
    }
    return state
}