mikumikugo

博客园 首页 新随笔 联系 订阅 管理

redux中最主要的东西就三个:store,reducer,action

store可以说是redux的躯干,由它撑起一个架子,所有被管理的状态也是由它存储(正如它的名字store)

action是描述所要执行的任务以及传递要进行操作的数据(如果需要的话)

reducer则是一个执行者,根据action中所描述的行为,执行定义好的操作(对数据进行处理),并将新的数据返回,(这个过程不应对原有的状态做出改变)

一、只含同步操作

1、建立reducer.js

import { combineReducers } from "redux"
import { hindleAddOrMinusReducer } from "./handleAddOrMinusReducer"
import { hindleShowOrHideReducer } from "./handleShowOrHideReducer"

//combineReducers用于将不同的reducer进行整个为一个reducer
//为什么会有多个reducer?
//进行项目开发时,常常时多人合作,每个人负责不同的业务,如果把所有的操作都放到一个reducer里,大家都对这个文件
//进行修改,会显得有些杂乱,所以针对不同的业务,建立不同的reducer文件,不仅结构更加清晰,且编码时也不会有
//不必要的冲突
const reducer = combineReducers({ hindleAddOrMinusReducer, hindleShowOrHideReducer })
export default reducer
hindleAddOrMinusReducer.js
const hindleAddOrMinusReducer = function (prevState = {
    count: 0
}, action) {
    const { type, payload } = action
    const newState = { ...prevState }
    switch (type) {
        case 'add':
            newState.count+=payload
            return newState
        case 'minus':
            newState.count-=payload
            return newState
        default:
            return prevState

    }

}
export { hindleAddOrMinusReducer }

 

hindleShowOrHideReducer.js
const hindleShowOrHideReducer = function (prevState = {
    isShow: true
}, action) {
    const { type, payload } = action
    const newState = { ...prevState }
    switch (type) {
        case 'show':
            newState.isShow = true
            return newState
        case 'hide':
            newState.isShow = false
            return newState
        default:
            return prevState

    }

}
export { hindleShowOrHideReducer }

2,建立action

hideOrShow.js

const show = function () {
    return {
        type: 'show'
    }
}
const hide = function () {
    return {
        type: 'hide'
    }
}
export { show, hide }

addOrMinus.js

const add = function (data) {
    return {
        type: 'add',
        payload: data
    }
}
const minus = function (data) {
    return {
        type: 'minus',
        payload: data
    }
}
export { add, minus }

 

3.建立store.js

import { createStore } from "redux";
import reducer from "./reducer/reducer";


const store = createStore(reducer)
export default store

 

4.建立App.js

注意:因为redux是第三方的库,因此其保存的状态更新后不会引起组件刷新,所以需要手动的调用react的this.setState({})方法(类式组件)、调用使用useState()创建的函数

或者使用redux的subscribe函数,该函数会在任意redux状态改变后执行,可以将根组件的render函数用store.subscribe(()=>{})包裹,每次redux状态改变后重新渲染所有组件

import React, { Component } from 'react'
import { add, minus } from './redux/action/addOrMinus'
import { hide, show } from './redux/action/hideOrShow'
import store from './redux/store'



export default class App extends Component {
    render() {
        return (
            <div>
                <p>当前值为:{store.getState().hindleAddOrMinusReducer.count}</p>
           <button onClick={() => { store.dispatch(add(2)); this.setState({}) }}>+2</button>&nbsp;<button onClick={() => { store.dispatch(minus(3)); this.setState({}) }}>-3</button> <div> {store.getState().hindleShowOrHideReducer.isShow && <div style={{ width: '100px', height: '100px', background: 'yellow' }}>我出来了</div>} <button onClick={() => { store.dispatch(show()); this.setState({}) }}>显示</button>&nbsp;<button onClick={() => { store.dispatch(hide()); this.setState({}) }}>隐藏</button> </div> </div> ) } }

-------------------------------------------------------------------------------------------分割线

运行时界面如下图所示

---------------------------------------------------------------------------------------------------------------分割线

点击+2按钮后

 

 
---------------------------------------------------------------------------------------------------------------分割线

点击-3按钮后

 

 

 

 

---------------------------------------------------------------------------------------------------------------分割线

点击隐藏按钮后

 

 ---------------------------------------------------------------------------------------------------------------分割线

点击显示按钮后

 二、redux里的异步操作

要在redux中进行异步操作,需要引入一个中间件来处理,就是redux-thunk,以及引入应用中间件的工具:applyMiddleware

1.建立getFilmsAction.js

里面包含一个axios请求,用来向网络中请求异步数据

import axios from "axios"

const getFilms = function () {
    return (dispatch) => {
        axios(
            {
                url: 'https://m.maizuo.com/gateway?cityId=110100&pageNum=1&pageSize=10&type=1&k=998385',
                headers: {
                    'X-Client-Info': '{ "a": "3000", "ch": "1002", "v": "5.2.0", "e": "16447435935369241695944705", "bc": "110100" }',
                    'X-Host': 'mall.film-ticket.film.list'
                }
            }
        ).then(res => {
            dispatch({
                type: 'getFilms',
                payload: res.data.data.films
            })
        }).catch()
    }
}
export { getFilms }

2.修改store.js

 引入thunk和applyMiddleware

import { createStore, applyMiddleware } from "redux";
import reducer from "./reducer/reducer";
import thunk from "redux-thunk";


const store = createStore(reducer, applyMiddleware(thunk))
export default store

3.建立getFilmsReducer.js

import { fromJS } from "immutable"
const getFilmsReducer = function (prevState = {
    films: []
}, action) {
    //进行深拷贝
    const newState = fromJS(prevState).toJS()
    const { type, payload } = action
    switch (type) {
        case 'getFilms':
            newState.films = payload
            return newState
        default:
            return prevState
    }

}
export { getFilmsReducer }

 

 4.App.js

import React, { Component } from 'react'
import { add, minus } from './redux/action/addOrMinus'
import { getFilms } from './redux/action/getFilmsAction'
import { hide, show } from './redux/action/hideOrShow'
import store from './redux/store'



export default class App extends Component {
    render() {
        return (
            <div>
                <p>当前值为:{store.getState().hindleAddOrMinusReducer.count}</p>
                <button onClick={() => { store.dispatch(add(2)); this.setState({}) }}>+2</button>&nbsp;<button onClick={() => { store.dispatch(minus(3)); this.setState({}) }}>-3</button>
                <div>
                    {store.getState().hindleShowOrHideReducer.isShow && <div style={{ width: '100px', height: '100px', background: 'yellow' }}>我出来了</div>}
                    <button onClick={() => { store.dispatch(show()); this.setState({}) }}>显示</button>&nbsp;<button onClick={() => { store.dispatch(hide()); this.setState({}) }}>隐藏</button>
                </div>
                <div>
                    <button onClick={() => { store.dispatch(getFilms()); this.setState({}) }}>获取电影列表</button>
                    <ul>
                        {
                            store.getState().getFilmsReducer.films.map((item) => {
                                console.log(store.getState().getFilmsReducer.films)
                                return <li key={item.filmId}>{item.name}</li>

                            })
                        }
                    </ul>
                </div>
            </div>

        )
    }
}

5.修改入口文件(添加store.subscribe()以达到实时更新)

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './02-redux-thunk/App';
import reportWebVitals from './reportWebVitals';
import store from './02-redux-thunk/redux/store'

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);
//订阅redux状态的改变来渲染APP组件
store.subscribe(() => {
  ReactDOM.render(
    <React.StrictMode>
      <App />
    </React.StrictMode>,
    document.getElementById('root')
  );
})

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

 

运行时初始界面

 

 

---------------------------------------------------------------------------------------------------------------------------------------分割线

点击‘获取电影列表’按钮

 

posted on 2022-02-22 17:08  mikumikugo  阅读(137)  评论(0编辑  收藏  举报