前言,对应的视频教程是B站技术胖的redux视频教程,本文内容是对应20-24节。
视频地址:https://www.bilibili.com/video/BV1w441137ss?p=21
项目代码地址:https://gitee.com/ling-xu/react-rudex-demo
对应此视频的系列笔记:
1-15节redux:https://blog.csdn.net/weixin_42349568/article/details/117196231
16-17节-redux-chunk:https://blog.csdn.net/weixin_42349568/article/details/117248649
18-19节-redux-saga:https://blog.csdn.net/weixin_42349568/article/details/117251408
20-24节-react-redux:https://blog.csdn.net/weixin_42349568/article/details/117266913
一,新建项目
1,创建新项目
npx create-react-app react-redux-demo
2,删除src下并不必要的文件(只保留index.js)
并修改index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<App />,
document.getElementById('root')
);
3,安装react-redux
npm i react-redux
4,基本的todolist组件
import React, { Component } from 'react';
class TodoList extends Component {
constructor(props) {
super(props);
this.state = { }
}
render() {
return (
<div>
<div>
<input></input>
<button>提交</button>
</div>
<ul>
<li>测试</li>
</ul>
</div>
);
}
}
export default TodoList;
5,安装redux
npm i redux
二,照常使用redux
但是,这样一来,只有todolist这个组件使用到了这个仓库,如果有很多组件,都需要这个仓库的话,难道每个组件都要引用一次嘛?那也太麻烦了,为了让多个组件都可以直接访问store仓库,引入了react-redux,其中Provider组件就是解决这个问题的。
三,Provider和connect的使用
1,使用provider组件包裹的组件,都可以访问store仓库:
import React from 'react';
import ReactDOM from 'react-dom';
import TodoList from './TodoList'
import {Provider} from 'react-redux'
import store from './store/index'
const App=(
<Provider store={store}>
<TodoList />
</Provider>
)
ReactDOM.render(
App,
document.getElementById('root')
);
2,使用connect和自定义映射函数获取store中的指定数据到组件参数中
import React, { Component } from 'react';
import {connect} from 'react-redux'
class TodoList extends Component {
render() {
return (
<div>
<div>
<input placeholder={this.props.inputValue}></input>
<button>提交</button>
</div>
<ul>
<li>测试</li>
</ul>
</div>
);
}
}
//自定义映射函数,传入的参数state是store中的state,返回的就是这个组件接收到的props对象
const stateToProps=(state)=>{
return {
inputValue:state.inputValue
//因为目前本组件只是用到inputValue这个值,所以只从store中取这个值,正常情况下可以取很多值
}
}
//连接函数,第一个参数就是自定义的映射函数,把store中的state映射到组件TodoList的参数props上
export default connect(stateToProps,null)(TodoList);
这样一来,就可以在本组件中使用到store中的inputValue参数了。
3,使用diapatch更新store中的数据
import React, { Component } from 'react';
import {connect} from 'react-redux'
class TodoList extends Component {
// inputChange(e){
// console.log(e.target.value)
// }
render() {
return (
<div>
<div>
<input
value={this.props.inputValue}
placeholder="亲输入"
onChange={this.props.inputChange}
></input>
<button>提交</button>
</div>
<ul>
<li>测试</li>
</ul>
</div>
);
}
}
//自定义映射函数,传入的参数state是store中的state,返回的就是这个组件接收到的props对象
const stateToProps=(state)=>{
return {
inputValue:state.inputValue
//因为目前本组件只是用到inputValue这个值,所以只从store中取这个值,正常情况下可以取很多值
}
}
const dispatchToProps=(dispatch)=>{
return {
inputChange(e){
const action={
type:'CHANGE_INPUT',
value:e.target.value
}
dispatch(action)
}
}
}
//连接函数,第一个参数就是自定义的映射函数,把store中的state映射到组件TodoList的参数props上
export default connect(stateToProps,dispatchToProps)(TodoList);
要修改store中的inputValue值,必然要发起diapatch(action),这里主要是这行代码:
const dispatchToProps=(dispatch)=>{
return {
inputChange(e){
const action={
type:'CHANGE_INPUT',
value:e.target.value
}
dispatch(action)
}
}
}
把inputChange映射为本组件的props中的一个方法,即传入的参数是dispatch函数,返回的对象中是绑定到本组件props中的方法(应该可以同时返回多个方法)。
然后利用连接函数的第二个参数上:
export default connect(stateToProps,dispatchToProps)(TodoList);
使用的时候:
<input
value={this.props.inputValue}
placeholder="亲输入"
onChange={this.props.inputChange}
></input>
4,对应的reducer处理:
const defaultState={
inputValue:'',
list:[]
}
const reducer=(state=defaultState,action)=>{
if(action.type==='CHANGE_INPUT'){
const newState=JSON.parse(JSON.stringify(state))
newState.inputValue=action.value
return newState
}
return state
}
export default reducer
5,完成新增事项的功能
todolist:
对应的reducer:
const defaultState={
inputValue:'',
list:[]
}
const reducer=(state=defaultState,action)=>{
if(action.type==='CHANGE_INPUT'){
const newState=JSON.parse(JSON.stringify(state))
newState.inputValue=action.value
return newState
}
if(action.type==='ADD_ITEM'){
const newState=JSON.parse(JSON.stringify(state))
newState.list.push(newState.inputValue)
newState.inputValue=''
return newState
}
return state
}
export default reducer
6,解构赋值简化代码
由上面的知识可以知道,connect函数把属性和方法全部映射到this.props这个对象中了,并且所有的属性和方法都在这个对象的第一层级上,于是就可以使用解构赋值的方式提取这些属性和方法,就不需要各种this.porps到处写了:
具体代码:
import React, { Component } from 'react';
import {connect} from 'react-redux'
class TodoList extends Component {
render() {
let {inputValue,list,clickBtn,inputChange}=this.props
return (
<div>
<div>
<input
value={inputValue}
placeholder="请输入"
onChange={inputChange}
></input>
<button onClick={clickBtn}>提交</button>
</div>
<ul>
{
list.map((item,index)=>{
return (
<li key={index}>{item}</li>
)
})
}
</ul>
</div>
);
}
}
//自定义映射函数,传入的参数state是store中的state,返回的就是这个组件接收到的props对象
const stateToProps=(state)=>{
return {
inputValue:state.inputValue,
list:state.list
//因为目前本组件只是用到inputValue这个值,所以只从store中取这个值,正常情况下可以取很多值
}
}
const dispatchToProps=(dispatch)=>{
return {
inputChange(e){
const action={
type:'CHANGE_INPUT',
value:e.target.value
}
dispatch(action)
},
clickBtn(){
const action={
type:'ADD_ITEM'
}
dispatch(action)
}
}
}
//连接函数,第一个参数就是自定义的映射函数,把store中的state映射到组件TodoList的参数props上
export default connect(stateToProps,dispatchToProps)(TodoList);