redux学习笔记(二)——react-redux基础知识

一、前言

上一节——redux基础知识中介绍了redux的基本使用。

但是在实际react项目中使用redux的话,一般不会使用原生redux,而是会再加上react-redux一起使用。

reduxreact-redux并没有什么关系,redux可以在任意地方使用,可以在react项目中使用,也可以在vue项目中使用,甚至可以在jQuery项目中使用。而react-redux是redux官方做的用于更好地与react进行配合。

这一节,将会在前一节redux的基础上,使用react-redux来让我们的组件更丝滑。

二、react-redux基础

2.1 react-redux简介

react-redux可以理解为是redux关于react项目的高级语法糖,他并不是redux,只是让你的redux代码在react项目中更丝滑。

react-redux中有两个重要的成员:

  • Provider
  • connect

下面将会详细介绍一下这两部分。

2.2 Provider标签

Provider是一个标签,他是一个react-redux封装的标签,用来包裹根组件用的,他的作用就是可以让你的整个应用都能随时随地的拿到store中的state

Provider标签有一个参数,props参数需要将store传递进去,然后通过context往下传递,使每个组件都能拿到store

  • 在app.js中引入Provider
import { Provider } from 'react-redux';
  • Provider包裹根节点
import { Provider } from 'react-redux';

ReactDOM.render(
  <Provider>
    <App />
  </Provider>
);
  • 给Provider传入store
import { Provider } from 'react-redux';
import store from './store';

ReactDOM.render(
  <Provider props={store}>
    <App />
  </Provider>
);

2.3 connect

虽然根节点外使用了Provider标签进行了包裹,但是Provider只是提供一个将store往下传递的能力,想要使用到store中的数据,就必须使用connect()方法对组件进行包裹(加强)。

  • 导入connect方法
import { connect } from 'react-redux';
  • connect的使用:

注意:调用connect()方法将会返回另一个方法,此时再将组件作为参数传入该方法进行包裹。

import { connect } from 'react-redux';
// 引入组件
import ComA from './ComA';

// 使用connect包裹组件
connect()(ComA);

这里使用了函数柯里化的概念,这种写法常用的地方是在工厂函数,如果有了解过express/koa/egg.js中间件的写法,应该就会对该种写法比较熟悉。

前面一部分connect()通过传入参数具体定制工厂函数的工作逻辑/模式,并返回一个函数,然后再将需要传入工厂函数的参数传入,运行工厂函数。

这里第一部分connect()方法的参数如下(按顺序):

参数名类型说明
mapstateToProps(state, ownProps)Function该函数会将store的数据绑定到组件上。
state: redux中的store
ownProps: 组件自己的props
mapDispatchToProps(dispatch, ownProps)Function该函数返回一个对象,该对象的每个属性就是一个action,会将这些action作为props绑定到组件上。
dispatch: 就是store.dispatch
ownProps: 组件自己的props
mergeProps(stateProps, dispatchProps, ownProps)Function不管是stateProps还是dispatchProps,都需要和ownProps merge之后才会被赋给我们的组件,通常情况下,你可以不传这个参数,connect就会使用object.assign替代该方法
optionsObjectconnect的其他配置项

其中,mapstateToPropsmapDispatchToProps是需要特别掌握的,这两个在开发过程中使用的频率最高也是最重要的部分。

  • 加上connect参数的写法
import { connect } from 'react-redux';
import ComA from './ComA';

// 定义mapstateToProps
const mapstateToProps = (state, ownProps) => {
  // ...
}

// 定义mapDispatchToProps
const mapDispatchToProps = (dispatch, ownProps) => {
  // ...
}

// 使用connect包裹组件
connect(mapstateToProps, mapDispatchToProps)(ComA);

其实也想把mapstateToPropsmapDispatchToProps使用示例贴上来,但是好像脱离实际使用的这部分代码反而让人看得云里雾里的。不如我们直接上项目吧。

三、Show me the code

本项目还是用一个计数器来进行展示吧。包含两个组件

  • 按钮组件:包含【+】和【-】按钮,点击按钮,显示组件显示内容也会随之改变
  • 显示组件:负责显示当前计数,默认值为0

3.1 新建项目

老样子,还是使用CRA工具来创建一个react项目:

# 创建项目
npx create-react-app react_redux_demo

# 进入项目目录
cd react_redux_demo

3.2 安装依赖

所需安装的依赖有两个:

  • redux
  • react-redux
npm i redux react-redux --save

3.3 添加reducer

和上一节一样的操作,在src目录下添加一个文件夹src/reducer,里面新建一个index.js文件。

  • src/reducer/index.js文件内容
// 设置一个默认的state
const initState = {
  value: 0
};

const reducer = (state = initState, action) => {
  switch(action.type) {
    case 'add':
      return { value: state.value + 1 };
    case 'decrese':
      return { value: state.value - 1 };
    default:
      return state;
  }
}

export default reducer;

3.4 添加store

和上一节一样的操作,在src目录下添加一个文件夹src/store,里面新建一个index.js文件。

  • src/store/index.js文件内容
import { createStore } from 'redux';

import reducer from '../reducer';

const store = createStore(reducer);

export default store;

3.5 修改index.js

因为根节点是在src/index.js文件中,所以直接到这里来进行一个Provider的包裹就行。当然,src/app.js中包裹也是没有问题的,但是要保证你的Provider标签把你要用到store的部分完全包裹起来。

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

// 导入Provider
import { Provider } from 'react-redux';

// 导入store
import store from './store';

// 使用Provider标签包裹根组件
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

3.6 完成按钮组件

按钮组件包含以下几部分:

  • 包含【+】和【-】按钮
  • 点击按钮,显示组件显示内容也会随之改变(修改store

src目录下新建一个Components/Button文件夹,并在其下创建index.js文件夹

  • src/Components/Button/index.js文件基本内容
function Button(props) {
  return (
    <>
      <button> + </button>
      <br />
      <button> - </button>
    </>
  );
}

export default Button;
  • 使用connect对组件进行包裹/增强
import { connect } from 'react-redux';

function Button(props) {
  return (
    <>
      <button> + </button>
      <br />
      <button> - </button>
    </>
  );
}

// 定义mapDispatchToProps
const mapDispatchToProps = (dispatch) => {
  
  // 返回一个对象,该对象每个方法就是一个action,所有的这些action都将绑定到组件的props参数上
  return {
    add: () => {
      dispatch({ type: 'add' });
    },
    decrese: () => {
      dispatch({ type: 'decrese' });
    }
  };
};

// 使用connect包裹/增强组件
// 这里不需要该组件获取store中的值,故第一个参数mapstateToProps就无需定义
export default connect(null, mapDispatchToProps)(Button);
  • 绑定按钮点击事件
import { connect } from 'react-redux';

function Button(props) {
  // 计数+1事件
  const addHandler = () => {
    props.add();
  };

  // 计数-1事件
  const decreseHandler = () => {
    props.decrese();
  };

  return (
    <>
      <button onClick={addHandler}> + </button>
      <br />
      <button onClick={decreseHandler}> - </button>
    </>
  );
}

// 定义mapDispatchToProps
const mapDispatchToProps = (dispatch) => {
  
  // 返回一个对象,该对象每个方法就是一个action,所有的这些action都将绑定到组件的props参数上
  return {
    add: () => {
      dispatch({ type: 'add' });
    },
    decrese: () => {
      dispatch({ type: 'decrese' });
    }
  };
};

// 使用connect包裹/增强组件
// 这里不需要该组件获取store中的值,故第一个参数mapstateToProps就无需定义
export default connect(null, mapDispatchToProps)(Button);

3.7 完成计数器显示组件

该组件只包含一个功能:

  • 显示当前计数

首先,在src目录下新建一个Components/Counter文件夹,并在其下创建index.js文件夹

  • src/Components/Counter/index.js文件基本内容
function Counter(props) {
  return (
    <div></div>
  );
}

export default Counter;
  • 使用connect包裹/增强组件
import { connect } from 'react-redux';

function Counter(props) {
  return (
    <div>{props.value}</div>
  );
}

// 定义mapstateToProps,直接将state进行返回
const mapstateToProps = (state) => {
  return state;
};

// 使用connect包裹/增强组件
// 该组件不需要发送action,所以无需传入mapDispatchToProps参数
export default connect(mapstateToProps)(Counter);

3.8 将组件添加到app.js中

src/app.js中,添加上述完成的两个组件:

import Button from './Components/Button';
import Counter from './Components/Counter';


function App() {
  return (
    <div className="App">
      <Button />
      <Counter />
    </div>
  );
}

export default App;

至此,一个完整的计数器就完成了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值