React之redux和react-redux

1、redux的使用:

(1)基本概念和 API:

1.1 Store

  • Store 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 Store。
  • Redux 提供createStore这个函数,用来生成 Store。
  • createStore函数接受另一个函数作为参数,返回新生成的 Store 对象。
import { createStore } from 'redux';
const store = createStore(reducer);

1.2 State

  • state就是store里面存储的数据,store里面可以拥有多个state,Redux规定一个state对应一个View,只要state相同,view就是一样的,反过来也是一样的,可以通过store.getState( )获取。

import {createStore} from 'redux'
const store=createStore(fn);
const state=store.getState()

1.3 Action

state的改变会导致View的变化,但是在redux中不能直接操作state也就是说不能使用this.setState来操作,用户只能接触到View。在Redux中提供了一个对象来告诉Store需要改变state。Action是一个对象其中type属性是必须的,表示Action的名称,其他的可以根据需求自由设置。

const action={
  type:'ADD_TODO',
  payload:'redux原理'
}

在上面代码中,Action的名称是ADD_TODO,携带的数据是字符串‘redux原理’,Action描述当前发生的事情,这是改变state的唯一的方式

1.4 store.dispatch( )

store.dispatch( )是view发出Action的唯一办法。

store.dispatch({
  type:'ADD_TODO',
  payload:'redux原理'
})

store.dispatch接收一个Action作为参数,将它发送给store通知store来改变state。

1.5 Reducer

  • Store收到Action以后,必须给出一个新的state,这样view才会发生变化。这种state的计算过程就叫做Reducer。
    Reducer是一个纯函数,他接收Action和当前state作为参数,返回一个新的state。
  • 注意:Reducer必须是一个纯函数,也就是说函数返回的结果必须由参数state和action决定,而且不产生任何副作用也不能修改state和action对象
const reducer =(state,action)=>{
  switch(action.type){
    case ADD_TODO:
        return newstate;
    default return state
  }
}

(2)redux 案例

src/index.js代码:

/**
 * src/index.js
 */
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import {createStore} from 'redux'
import reducer from './reducers/counter'

// 创建仓库,参数是reducer
const store = createStore(reducer)

const renderDom = () => {
  ReactDOM.render(
    <React.StrictMode>
      {/* 父组件传值给子组件,value就是获取状态中的值,onIncrement和onDecrement是一个执行dispatch的函数 */}
      <App
        value = {store.getState()}
        onIncrement={() => {store.dispatch({type: "INCREMENT"})}}
        onDecrement={() => {store.dispatch({type: "DECREMENT"})}}
      />
    </React.StrictMode>,
    document.getElementById('root')
  );
}
renderDom();

// 监听数据变化,只要state变化,就会重新执行renderDom函数
store.subscribe(renderDom)

src/reducers/counter.js 代码

/**
 * src/reducers/counter.js
 */
import * as constants from './../constants'

const counter = (state=0, action) => {
  switch(action.type) {
    case constants.INCREMENT:
      return state+1;
    case constants.DECREMENT:
      return state-1
    default:
      return state;
  }
}

export default counter

src/App.js 代码

/**
 * src/App.js
 */
import React from 'react';

export default class App extends React.Component{
  render() {
    console.log (this.props)
    let {value, onIncrement, onDecrement} = this.props
    return (
      <div className="App">
        <p>{value}</p>
        <button onClick={onIncrement}>加1</button>
        <button onClick={onDecrement}>减1</button>
      </div>
    )
  }
}

2、react-redux

  • 由于上面使用redux时,每次修改state都要重新调用render函数。于是引入了react-redux。

 src/index.js 代码

/**
 * src/index.js
 */
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import {createStore} from 'redux'
import reducer from './reducers/counter'
// 引入react-redux中的Provider,是一个组件,只要包含在这个组件内的页面都可以使用store
import { Provider } from "react-redux"

// 创建仓库,参数是reducer
const store = createStore(reducer)

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);

src/App.js 代码

/**
 * src/App.js
 */
import React from 'react';
import {connect} from 'react-redux'
import {increment, decrement} from './actions/counter'

class App extends React.Component{
  render() {
    console.log (this.props)
    let {counter, increment, decrement} = this.props
    return (
      <div className="App">
        <p>{counter}</p>
        <button onClick={()=>increment(5)}>加</button>
        <button onClick={()=>decrement(10)}>减</button>
      </div>
    )
  }
}

const mapStateToProps = (state) => {
  return {
    counter:state
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    increment: (num) => {dispatch(increment(num))},
    decrement: (num) => {dispatch(decrement(num))}
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(App)

其中,新增了actions/counter.js文件

import * as constants from './../constants'

export function increment (num) {
  console.log(num)
  return {
    type: constants.INCREMENT,
    num
  }
}

export function decrement (num) {
  return {
    type: constants.DECREMENT,
    num
  }
}

如果 actions/counter.js 中很多方法,调用起来就很复杂,可以整合一下。

src/App.js 代码

/**
 * src/App.js
 */
import React from 'react';
import {connect} from 'react-redux'
// import {increment, decrement} from './actions/counter'
import * as counterActions from './actions/counter'
import {bindActionCreators} from 'redux'

class App extends React.Component{
  render() {
    console.log (this.props)
    let {counter, counterActions} = this.props
    return (
      <div className="App">
        <p>{counter}</p>
        <button onClick={()=>counterActions.increment(5)}>加</button>
        <button onClick={()=>counterActions.decrement(10)}>减</button>
      </div>
    )
  }
}

const mapStateToProps = (state) => {
  return {
    counter:state
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    counterActions: bindActionCreators(counterActions, dispatch)
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(App)

 

现在是只有一个counter模块,如果又有user模块的数据,那就要使用到combineReducers了

reducers文件夹里新建user.js文件,创建一个user的reducers

import { FETCH_USER_SUCCESS } from "../constants"

const initialState = {
  user:{}
}

const user = ( state = initialState,action ) => {
  switch(action.type){
      case FETCH_USER_SUCCESS:
          return {
              user: action.user
          };
      default:
          return state;
  }
}

export default user

reducers文件夹里新建index.js文件,将两个reducers整个起来。

import { combineReducers } from "redux"
import counter from "./counter"
import user from "./user"

const rootReducer = combineReducers({
    counter,
    user
})

export default rootReducer

index.js引入

import rootReducer from "./reducers"

const store = createStore(rootReducer)

在actions文件夹里新建user.js

import { FETCH_USER_SUCCESS } from "../constants"

export const get_user = (user) => {
    return {
        type: FETCH_USER_SUCCESS,
        user
    }
};

新建user页面

import React from 'react'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
import * as userActions from './../actions/user'

class User extends React.Component{
  render () {
    let {user, userActions} = this.props
    console.log(user, userActions)
    return(
      <div>
        {
          Object.keys(user.user).length === 0 ? <p>User</p> : <p>{user.user}</p>
        }
          <button onClick={ () => { userActions.get_user('gfz') } }>getUser</button>
      </div>
    )
  }
}

const mapStateToProps = (state) => {
  return {
    user: state.user
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    userActions: bindActionCreators(userActions,dispatch)
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(User)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值