React学习笔记——react-redux的使用

前言

react-redux不同于redux,前者的诞生是由于react出品方认为使用ruduxreact使用者太多了,进而Facebook公司自己出了react-redux来更好的优化react的使用。

使用 react-redux

  • 安装 react-redux
yarn add react-redux
  • react-redux 中,将组件分为两类:UI组件、容器组件

1. UI组件
1)只负责 UI 的呈现,不带有任何业务逻辑
2)通过props接收数据(一般数据和函数)
3)不使用任何 Redux 的 API
4)一般保存在components文件夹下

2. 容器组件
1)负责管理数据和业务逻辑,不负责UI的呈现
2)使用 Redux 的 API
3)一般保存在containers文件夹下

  • 其中,UI组件,不涉及 redux 相关代码,由 容器组件充当桥梁进行沟通,如下:React学习笔记——react-redux的使用_第1张图片

相关API

  1. Provider:让所有组件都可以得到state数据
<Provider store={store}>
  <App />
</Provider>
  1. connect:用于包装 UI 组件生成容器组件
import { connect } from 'react-redux'
  connect(
    mapStateToprops,
    mapDispatchToProps
  )(Counter)
  1. mapStateToprops:将外部的数据(即state对象)转换为UI组件的标签属性
const mapStateToprops = function (state) {
  return {
    value: state
  }
}
  1. mapDispatchToProps:将分发action的函数转换为UI组件的标签属性
    在redux基本使用的demo基础上,进行修改:

目录结构:
React学习笔记——react-redux的使用_第2张图片

  • components\Count\index.jsx(UI组件
    该文件中不再含有和rudux相关的指令
import React, { Component } from 'react'

export default class Count extends Component {

	state = {carName:'奔驰c63'}

	//加法
	increment = ()=>{
		const {value} = this.selectNumber
		this.props.jia(value*1)
	}
	//减法
	decrement = ()=>{
		const {value} = this.selectNumber
		this.props.jian(value*1)
	}
	//奇数再加
	incrementIfOdd = ()=>{
		const {value} = this.selectNumber
		if(this.props.count % 2 !== 0){
			this.props.jia(value*1)
		}
	}
	//异步加
	incrementAsync = ()=>{
		const {value} = this.selectNumber
		this.props.jiaAsync(value*1,500)
	}

	render() {
		//console.log('UI组件接收到的props是',this.props);
		return (
			<div>
				<h1>当前求和为:{this.props.count}</h1>
				<select ref={c => this.selectNumber = c}>
					<option value="1">1</option>
					<option value="2">2</option>
					<option value="3">3</option>
				</select>&nbsp;
				<button onClick={this.increment}>+</button>&nbsp;
				<button onClick={this.decrement}>-</button>&nbsp;
				<button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>&nbsp;
				<button onClick={this.incrementAsync}>异步加</button>&nbsp;
			</div>
		)
	}
}
  • containers\Count\index.jsx(容器组件
    该文件用于书写和redux相关的桥梁代码
    核心函数——从react-redux中暴露的方法connect
//引入Count的UI组件
import CountUI from '../../components/Count'
//引入action
import {
	createIncrementAction,
	createDecrementAction,
	createIncrementAsyncAction
} from '../../redux/count_action'

//引入connect用于连接UI组件与redux
import {connect} from 'react-redux'

/* 
	1.mapStateToProps函数返回的是一个对象;
	2.返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value
	3.mapStateToProps用于传递状态
*/
function mapStateToProps(state){
	return {count:state}
}

/* 
	1.mapDispatchToProps函数返回的是一个对象;
	2.返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value
	3.mapDispatchToProps用于传递操作状态的方法
*/
function mapDispatchToProps(dispatch){
	return {
		jia:number => dispatch(createIncrementAction(number)),
		jian:number => dispatch(createDecrementAction(number)),
		jiaAsync:(number,time) => dispatch(createIncrementAsyncAction(number,time)),
	}
}

//使用connect()()创建并暴露一个Count的容器组件
export default connect(mapStateToProps,mapDispatchToProps)(CountUI)
  • App.jsx
import React, { Component } from 'react'
import Count from './containers/Count'
import store from './redux/store'

export default class App extends Component {
	render() {
		return (
			<div>
				{/* 给容器组件传递store */}
				<Count store={store} />
			</div>
		)
	}
}
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import store from './redux/store'

ReactDOM.render(<App/>,document.getElementById('root'))

//监测redux中状态的改变,如redux的状态发生了改变,那么重新渲染App组件
store.subscribe(()=>{
	ReactDOM.render(<App/>,document.getElementById('root'))
})

注:store.subsrcibe()方法可以不用在调用了,因为在使用了react-redux之后,若store的状态有改变,react-redux会自动的刷新页面,展示最新数据。

redux文件夹中的四个文件constant.jscount_action.jscount_reducer.jsstore.js没有改动

使用的优化

使用 Provider

  • 在使用 react-redux时,我们需要通过 props 将 store,传递给容器组件

  • 但如果容器组件有很多,每个都需要传store,那么对我们来说,会很麻烦

  • 因此,使用 Provider,并给 Provider 传递 store,那么 Provider 会自动传递store给所有 容器组件

  • App.js

import React, { Component } from 'react'
import Count from './containers/Count'

export default class App extends Component {
  render() {
    return (
      <div>
        <Count/>	{/* 不需要自己再传递 store */}
      </div>
    )
  }
}

index.js

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

// 借助  Provider 统一传递
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>
  , document.getElementById('root'));

整合UI组件跟容器组件

  • 因为UI 组件不需要我们渲染,而是直接由 react-reduxconnect方法,生成容器组件
  • 所以,我们常常将 UI 组件 跟 容器组件 写成一个 文件,仅暴露容器组件即可,如下:
  • 通常 整合后的组件,放在 containers 文件夹
  • containers\Count\index.jsx
import React, { Component } from 'react'
//引入action
import {
	createIncrementAction,
	createDecrementAction,
	createIncrementAsyncAction
} from '../../redux/count_action'
//引入connect用于连接UI组件与redux
import {connect} from 'react-redux'

//定义UI组件
class Count extends Component {

	state = {carName:'奔驰c63'}

	//加法
	increment = ()=>{
		const {value} = this.selectNumber
		this.props.jia(value*1)
	}
	//减法
	decrement = ()=>{
		const {value} = this.selectNumber
		this.props.jian(value*1)
	}
	//奇数再加
	incrementIfOdd = ()=>{
		const {value} = this.selectNumber
		if(this.props.count % 2 !== 0){
			this.props.jia(value*1)
		}
	}
	//异步加
	incrementAsync = ()=>{
		const {value} = this.selectNumber
		this.props.jiaAsync(value*1,500)
	}

	render() {
		//console.log('UI组件接收到的props是',this.props);
		return (
			<div>
				<h1>当前求和为:{this.props.count}</h1>
				<select ref={c => this.selectNumber = c}>
					<option value="1">1</option>
					<option value="2">2</option>
					<option value="3">3</option>
				</select>&nbsp;
				<button onClick={this.increment}>+</button>&nbsp;
				<button onClick={this.decrement}>-</button>&nbsp;
				<button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>&nbsp;
				<button onClick={this.incrementAsync}>异步加</button>&nbsp;
			</div>
		)
	}
}

//使用connect()()创建并暴露一个Count的容器组件
export default connect(
	state => ({count:state}),

	//mapDispatchToProps的一般写法
	/* dispatch => ({
		jia:number => dispatch(createIncrementAction(number)),
		jian:number => dispatch(createDecrementAction(number)),
		jiaAsync:(number,time) => dispatch(createIncrementAsyncAction(number,time)),
	}) */

	//mapDispatchToProps的简写
	{
		jia:createIncrementAction,
		jian:createDecrementAction,
		jiaAsync:createIncrementAsyncAction,
	}
)(Count)

注:此处mapDispatchToProps的简写并没有调用dispatch方法,原因是:由于引入了react-redux,在调用conncet方法时,他会识别connect(a,b)()中参数b是否对应的是action,若是action类别,则会自动调用dispatch方法进行打包,从而简化代码书写。

效果:
React学习笔记——react-redux的使用_第3张图片

你可能感兴趣的:(React,react,react-redux)