Redux基本使用

9 篇文章 0 订阅

如果你静不下来的话,去学习redux感觉有点难,静下来去学,一遍不懂再来一遍,哪TM有人是天生就会的?
先理解一下定义!!!(也可以看官网,最主要看基本概念)

源码

源码

Action

Action:是把数据从应用 (译者注:这里之所以不叫 view 是因为这些数据有可能是服务器响应的,用户输入或者其他非 view 的数据) 传到 store 的有效载荷。它是 store 数据的 唯一 来源。一般来说你会通过store.dispatch() 将action 传到 store。

Action 本质是 JavaScript 普通对象。我们约定,action 内必须使用一个字符串类型的 type 字段来表示将要执行的动作。多数情况下, type 会被定义成字符串常量,当应用规模越来越大时,建议使用单独的模块或文件来存放 action。


Reducer

Reducer 指定了应用状态的变化如何响应 actions 并发送到 store 的,记住 actions 只是描述了 有事情发生了 这一事实,并没有描述应用如何更新 state。

一会的例子中:使用 combineReducers() 将多个 reducer 合并成为一个。现在我们将其导入,并传递 createStore()

import {createStroe} from 'redux';
//这里的reducers 是把所有的reducer合并为一个
import reducers from './reducers.js'

let store = createStore(reducers)

设计 State 结构(理解就看,不看没关系)

  1. 在 Redux 应用中,所有的 state 都被保存在一个单一对象中。建议在写代码前先想一下这个对象的结构。如何才能以最简的形式把应用的 state 用对象描述出来?
  2. 通常,这个 state 树还需要存放其它一些数据,以及一些 UI 相关的 state。这样做没问题,但尽量把这些数据 与 UI 相关的 state 分开。

Stroe

我们知道 action 来描述 “发生了什么”,和使用 reducer 来根据 action 更新 state 的用法。

Store 就是把他们联系到一起的对象。Store 有一下职责:

  1. 维持应用的 state
  2. 提供 getState() 方法获取 state
  3. 提供 dispatch(action) 方法更新 state
  4. 通过 subscribe(listener) 注册监听器
  5. 通过 subscribe(listener) 返回的函数注销监听器

:再次强调一下 Redux 应用只有一个单一的 store 。当需要拆分数据处理逻辑时,你应该使用 reducer组合 而不是创建多个 store。


流程图

在这里插入图片描述
简单流程: React组件会通过 dispatch(action),发送一条指令给 对应的reducer,action中携带我们传过去的数据,reducer 对数据进行处理,形成新的 state,然后交给 store ,然后store仓库通过 connect 再更新返回到视图层的组件。


通过例子来理解redux

这个是一个 用户登录 数据状态的例子!

  1. 安装
    npm install redux react-redux -S
  2. 如果使用 redux ,就立刻在 src文件目录下建立 actions、reducers、store 这三个文件夹。
  3. 有一点你可以把一些常量,或者说全局的 (通俗点的就是在这里你能用到,在另外一个地方你也能用到) 就单独的新建一个文件,我这里 新建了 constants 文件夹。

目录结构:
在这里插入图片描述


constants文件

这个文件夹,就是存放我的一些常量或者全局性质;
在此文件夹中新建一个 user.js文件

// 用户登录、退出、更新
export const USER_LOGIN = "USER_LOGIN"
export const USER_LOGOUT = "USER_LOGOUT"
export const USER_UPDATE = "USER_UPDATE"

actions文件

看文件名加 s ,就表明这里放的是所有的action,用redux第一步就是先定义你的 action
在此文件夹中新建一个 user.js文件 ;(这里把所有的action放到讴歌模块里了)

// 先定义好redux的几种action,action 就是一个对象,它带有一些描述,带一些数据
//在app组件中通过dispatch(action) 方法,发出一个action,触发action更新,action更新,进入reducer中进行数据处理,

import * as userConstants from '../constants/user.js';

// 这里的每个 action 接受一个参数data;(名字无所谓有意义就行)
export const login = (data) => {
    return {
    	//这个是action中的type,是个必须属性
        type: userConstants.USER_LOGIN,
        data:data
    }
}

export const logout = (data) => {
    return {
        type: userConstants.USER_LOGOUT,
        data
    }
}

export const update = (data) => {
    return {
        type: userConstants.USER_UPDATE,
        data
    }
}

reducers文件

看文件名就明白,这里是放的所有的reducer
在此文件中,新建一个 user.js文件 作为一个reducer;

//reducer 功能是用来做数据处理的

import * as userConstants from '../constants/user.js';


//判断传过来的action的数据和信息(action必带的一个属性就是 type),通过判断type,来决定做什么事
//state 给默认状态
export default function (state = {}, action) {
    switch (action.type) {
        case userConstants.USER_LOGIN: {
            return {
                ...state,//保留以前的state数据
                ...action.data,
                isLogin: true,//进行特殊的处理,比如登录的时候给他一个这个数据
            }
        }
        case userConstants.USER_LOGOUT: {
            return {
                // 退出的时候,把数据清空了,只剩这一个
                isLogin: false
            }
        }
        case userConstants.USER_UPDATE: {
            return {
                ...state,
                ...action.data,//action携带的数据,如果携带的数据包括旧的state的数据,那么就会覆盖,从而达到更新
            }
        }
        default: {
            return state
        }
    }
}


store文件

store仓储管理state,一个redux应用只有单一一个 store,文件名都没有加 s ;
在此文件夹下新建一个 index.js文件;(这个文件命名有意义就行)

//通过 createStore() 函数来创建 store仓储
import { createStore } from 'redux';
import reducer from '../reducers/user.js';

// 通过一个函数来完成创建 store,这只是一个创建store的生成器,不会立马创建store 
export default function Store(initState) {
	// 第一个参数:就是传入的reducer
	// 第二个参数就是初始化一下这个仓储,先给他默认的初始化数据
    // 创建store的时候,还有第三个参数,用来启动第三方浏览器中redux的调试工具
    return createStore(reducer, initState, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())
}

:到这里还没有完,还没有创建好store仓储实例,上边他只是一个创建store的生成器!!!


创建store

创建store 是在src目录下的 index.js 中创建!!!

//redux 只是做状态管理的,它跟react没有关系,需要通过 react-redux 来建立关系;
import { Provider } from 'react-redux';

// 把用来创建store的仓库生成器引用过来,要在这里进行创建store
import Store from './store/index.js';


// 通过Store() 创建具体的store实例,并进行传参(初始化仓储的默认数据);
const store = Store({
    user: {
        isLogin: false
    }
})


ReactDOM.render(
    // 把组件放入到 Provider中,并且把创建的store传过去
    <Provider store={store}>
        <App />
    </Provider>
    , document.getElementById('root'));

connect函数

以上基本的redux基本搭建好了,但是想要在页面上(组件中)拿到具体的redux数据,需要通过react-redux的 connect()函数
App组件中引入 connect函数,并且通过页面显示

// 基本的redux 搭建好后,想要在页面上拿到具体的redux数据,需要通过react-redux 的 connect函数
import { connect } from 'react-redux'


class App extends Component {
  render() {
  	// 通过控制台看一下数据
    console.log(this.props)

    const { user } = this.props
    return (
      <div className="App">
        用户状态↓
        <div>
        	//这里页面会显示未登录,因为创建仓储的时候传的isLogin:false
          {user.isLogin ? '欢迎你' : '未登录'}
        </div>
      </div>
    );
  }
}
// 把数据交给store仓库,然后通过connect,再返回到视图层的react组件。
export default connect((state) => {
  return {
    user: state.user
  }
})(App);

到这里redux的基本搭建就完成了!


dispatch(action) 更新

通过 dispatch() 函数进行更新,这例的参数是你定义的 action,用哪个传哪个
例子:通过点击按钮来更新用户的状态;


在App组件中

//dispatch(action) 需要一个action参数,所以先导入你的action
import * as userActions from './actions/user.js';

class App extends Component {
  render() {
    console.log(this.props)

    const { user } = this.props
    return (
      <div className="App">
        用户状态↓
        <div>
          {user.isLogin ? '欢迎你' : '未登录'}
        </div>
         {/* 通过触发 login这个action,进行数据的更新,并且再多传一下两个参数,点击按钮,用户状态将变成,已登录,因为login所对应的reducer数据处理,isLogin:true */}
        <button onClick={() => {
          this.props.dispatch(userActions.login({ account: "test", password: "123" }))
        }}>登录</button>
      </div>
    );
  }
}

在浏览器中启动redux-devtools工具

  1. 在谷歌浏览器中添加这个 redux-devtools 这个扩展,并且打开!!
  2. 然后在 createStore() 这个函数里有有三个参数,第三个参数就是用来启用第三方redux-devtools 工具,代码如下:
createStore(xxx, xxx, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())

补充

这些补充的代码还是在案例的基础上修改或者添加的。

在上边的案例中,只用到了一个reducer,但是在实际中,可能会有多个reducer,但是在createStore() 创建store仓储的时候,只能传入一个reducer,那么就要通过 combineReducers 把所有的reducer合并起来


在reducers文件夹添加第二个reducer

在reducers中添加 city.js 文件,作为第二个reducer

//city.js文件

export default function (state = {}, action) {
    switch (action.type) {
        case "CITY_UPDATE": {
            return {
                ...state,
                ...action.data
            }
        }
        case "CITY_CLEAR": {
            return {
                // 清空,返回空对象
            }
        }
        default: {
            return state
        }
    }
}

这个时候就已经有多个reducer了,然后需要把这两个reducer进行合并,合并他们依旧是reducer,所以在reducers文件夹下新建一个合并的index.js文件

// 在创建store的时候,只能传一个reducer,所以把所有的reducer据合起来
import { combineReducers } from 'redux'


// 引入两个reducer
import user from './user.js';
import city from './city.js';


export default combineReducers({
    user: user,
    city
})

合并完成后,在store文件下的idnex.js文件中引入

// 这个reducer是聚合了所有的reducer的一个reducer;(这个引入文件路径已经变了)
import reducer from '../reducers/index.js';


// 把store仓储初始一下,给一个初始的数据参数(这里创建store只能传一个reducer,但是好多个reducer,所以把所有reducer聚合一下)
export default function Store(initState) {
    // 创建store的时候,还有第三个参数,用来启动第三方redux的插件工具
    return createStore(reducer, initState, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())
}

在创建store仓储的时候,初始化的时候给默认初始化数据

//在index.js文件中创建store仓储

const store = Store({
    user: {
        isLogin: false
    },
    city: {
        "029": "北京"
    }
})

:到这里就已经完成了!!,如果你有 redux-devtools 的话,你可以查看state


点击按钮前
在这里插入图片描述


点击按钮后(更新后)
在这里插入图片描述

异步操作redux-thunk

此例子,修改为异步action,完善用户登录状态显示

异步action

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值