react项目配置及redux使用流程(详细记录)

算法踏雪人
• 阅读 5011

react项目配置及redux使用流程(详细记录)

以TodoList为例,项目地址:https://github.com/mandyshen9...

react项目创建及配置

首先创建react项目:

creact-react-app reactdemo

修改默认配置:

create-react-app 的默认配置进行自定义,这里我们使用 react-app-rewired(一个对 create-react-app 进行自定义配置的社区解决方案)。

$ yarn add react-app-rewired customize-cra

修改package.json:

/* package.json */
"scripts": {
-   "start": "react-scripts start",
+   "start": "react-app-rewired start",
-   "build": "react-scripts build",
+   "build": "react-app-rewired build",
-   "test": "react-scripts test",
+   "test": "react-app-rewired test",
}

然后在项目根目录创建一个 config-overrides.js 用于修改默认配置。

module.exports = function override(config, env){
  // do staff with the webpack config...
  return config
}

配置按需加载:

babel-plugin-import 是一个用于按需加载组件代码和样式的 babel 插件(原理),现在我们尝试安装它并修改 config-overrides.js 文件。

yarn add babel-plugin-import

修改config-overrides.js文件:

const { override, fixBabelImports } = require('customize-cra')
module.exports = override(
  fixBabelImports('import',{
    libraryName: 'antd', // 或其他第三方组件库名称
    libiaryDirectory: 'es', // 组件位置
    style: 'css',
  })
)

配置less

配置less: 我们可以引入 customize-cra 中提供的 less 相关的函数 addLessLoader 来帮助加载 less 样式,同时修改 config-overrides.js 文件如下。

yarn add less less-loader
const { override, fixBabelImports, addLessLoader } = require('customize-cra')
module.exports = override(
  fixBabelImports('import',{
    libraryName: 'antd', // 或其他第三方组件库名称
    libiaryDirectory: 'es', // 组件位置
    style: true,
  }),
  addLessLoader({
    javascriptEnabled: true,
  })
)

<hr/>
<hr/>

redux的使用

react项目配置及redux使用流程(详细记录)

安装redux:

yarn add redux

从图片中可以看出,Redux工作流程中有四个部分,最重要的就是store这个部分,因为它把所有的数据都放到了store中进行管理。在编写代码的时候,因为重要,所以要优先编写store。

(1)创建src/store/index.js,就是整个项目的store文件。

/**
 * index.js 文件就是整个项目的store文件
 */

import { createStore } from 'redux' // 引入 createStore方法
import reducer from './reducer' // 引入reducer
const store = createStore(
  reducer,
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() // 使浏览器中redux-devtool插件生效
) // 创建数据存储仓库
export default store // 将仓库暴露出去

(2)创建src/store/reducer.js,有管理能力的模块。

store只是一个仓库,它并没有管理能力,它会把接收到的action自动转发给reducer。

/**
 * reducer暴露出去的就是一个方法函数,有两个参数:state 和 action。
 * state: 是整个项目中需要管理的数据信息。
 */

/**
 * 一定要注意: reducer里只能接收state,不能改变state。
 * 不要认为把业务逻辑写在了reducer中,那改变state值的一定是reducer。
 * 其实不然,reudcer只是返回了更改的数据,操作的是newState,但是并没有更改store中的state数据,store拿到了reducer的数据,自己对自己进行了更新。
 */
const defaultState = {} // 默认数据
export default (state = defaultState, action) => {
  if (action.type === CHANGE_INPUT) {
    let newState = JSON.parse(JSON.stringify(state)) // 深度拷贝state
    newState.inputValue = action.value
    return newState
  }
  if (action.type === ADD_ITEM) {
    let newState = JSON.parse(JSON.stringify(state))
    newState.list.push(newState.inputValue)  //push新的内容到列表中去
    newState.inputValue = ''
    return newState
  }
  // 其他类似操作流程...
  return state
}

(3)组件获取state中的数据。

import store from '../store/index' // 在组件中引入store

class TodoList extends Component {
  constructor(props) {
    super(props)
    this.state = store.getState() // 从store中获取state数据
    store.subscribe(this.storeChange) // 订阅Redux的状态
  }

  /**
   * 当订阅的redux状态变化时,使用setState()方法,将新的数据存入state中。
   */
  storeChange = () => {
    this.setState(store.getState())
  }
}

(4) 创建src/store/actionTypes.js

如果需要action的地方我们就自己命名一个type,会出现两个基本问题:

  • 这些types如果不统一管理,不利于大型项目的复用,甚至会产生冗余代码。
  • 因为action里的type,一定要和reducer里的type一一对应,所以这部分代码或字母写错后,浏览器里并没有明确的报错,这给调试带来了极大的困难。

所以新建立一个actionTypes.js文件,然后把type集中放到文件中进行管理。

export const ADD_ITEM = 'addItem'
export const // ...
// ...

(5) 创建src/store/actionCreators.js

把所有的redux action放到一个文件里进行管理。

import { CHANGE_INPUT, ADD_ITEM, DELETE_ITEM, GET_LIST } from './actionTypes'

export const changeInputAction = (value) => ({
  type: CHANGE_INPUT,
  value
})

export const addItemAction = () => ({
  type: ADD_ITEM
})

export const deleteItemAction = (index) => ({
  type: DELETE_ITEM,
  index
})

export const getListAction = (data) => ({
  type: GET_LIST,
  data
})

// ...

下面通过button的点击事件来熟悉redux流程。

组件:

import React, { Component } from 'redux'
import { addItemAction } from '.././store/actionCreators'

class List extends Component {
  constructor(props){
    super(props)
    this.state = store.getState()
    store.subscribe(this.storeChange)
  }
  storeChange = () => {
    this.setState(store.getState())
  }

  clickBtn = () => {
    action = addItemAction() // 返回一个对象{type: ADD_ITEM}
    store.dispatch(action) // 通过dispatch()方法将action传递给store
  }

  render(){
    return(
      <div>
        <button onClick={this.clickBtn}>增加</button>
      <div/>
    )
  }
}

store/index.js,整个项目的store文件:

// store/index.js
import { createStore } from 'redux' // 引入 createStore方法
import reducer from './reducer' // 引入reducer
const store = createStore(
  reducer,
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
) // 创建数据存储仓库
export default store // 将仓库暴露出去

store/reducer.js:

// store/reducer.js
import { ADD_ITEM } from './actionTypes'

const defaultState = {
  inputValue: 'Write Something',
  list: []
} // 默认数据

export default (state = defaultState, action) => {
  if (action.type === ADD_ITEM) {
    let newState = JSON.parse(JSON.stringify(state))
    newState.list.push(newState.inputValue)  //push新的内容到列表中去
    newState.inputValue = ''
    return newState
  }
  return state
}

store/actionTypes.js:

// store/actionTypes.js
export const ADD_ITEM = 'addItem'

store/actionCreators.js:

// store/actionCreators.js
import { ADD_ITEM } from './actionTypes'

export const addItemAction = () => ({
  type: ADD_ITEM
})
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Easter79 Easter79
3年前
sql注入
反引号是个比较特别的字符,下面记录下怎么利用0x00SQL注入反引号可利用在分隔符及注释作用,不过使用范围只于表名、数据库名、字段名、起别名这些场景,下面具体说下1)表名payload:select\from\users\whereuser\_id1limit0,1;!(https://o
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Easter79 Easter79
3年前
SpringBoot自定义序列化的使用方式
场景及需求:项目接入了SpringBoot开发,现在需求是服务端接口返回的字段如果为空,那么自动转为空字符串。例如:\    {        "id":1,        "name":null    },    {        "id":2,        "name":"x
Stella981 Stella981
3年前
Redux入门实战——todo
1.前言在之前的博客中,我写了一篇关于todolist实现的博客,一步一步详细的记录了如何使用基础的React知识实现一个React单页面应用,通过该篇文章,能够对React入门开发有一个直观的认识和粗浅的理解。近期,个人学习了一下Redux,又将该项目使用ReactRedux的方式进行了实现。本片内容记录以下实践的过程。通过本实例,
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
Linux日志安全分析技巧
0x00前言我正在整理一个项目,收集和汇总了一些应急响应案例(不断更新中)。GitHub地址:https://github.com/Bypass007/EmergencyResponseNotes本文主要介绍Linux日志分析的技巧,更多详细信息请访问Github地址,欢迎Star。0x01日志简介Lin
Stella981 Stella981
3年前
SpringBoot自定义序列化的使用方式
场景及需求:项目接入了SpringBoot开发,现在需求是服务端接口返回的字段如果为空,那么自动转为空字符串。例如:\    {        "id":1,        "name":null    },    {        "id":2,        "name":"x
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
算法踏雪人
算法踏雪人
Lv1
是谁,在寒冷的冬天,掀开被单,冰冻爱情的温暖。
文章
5
粉丝
0
获赞
0