[react基础] redux react-redux

  • Post author:
  • Post category:其他


在这里插入图片描述

案例:

点击按钮,数字+1,初始值100

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述



单用户模块化拆分

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

src/store/action.js

在这里插入图片描述

src/store/index.js

在这里插入图片描述

src/store/reducer.js

在这里插入图片描述

src/store/mutation.js

在这里插入图片描述

小分析:

在这里插入图片描述



代码

在这里插入图片描述

index.js

import React from 'react';
import ReactDOM from 'react-dom';
// 根组件
import App from './App';
import store from './store'

// 定义本项目的路由模式
// BrowserRouter  history模式
// HashRouter     hash模式
import { BrowserRouter as Router } from 'react-router-dom'

ReactDOM.render(
  <Router>
    <App />
  </Router>
  document.getElementById('root')
);

App.js

import React, { Component } from 'react';
// 引入redux的数据仓库
import store from './store'
import { incrAction } from './store/action'


class App extends Component {

  // 只执行一次
  state = {
    title: '标题',
    // store.getState() 返回的是state对象数据
    ...store.getState()
  }
  unSubscribe = null

  componentDidMount() {
    // 订阅redux中的数据是否有更改,如果有,则需要通知当前组件更新一次
    // this.setState({key:value})
    // subscribe方法返回一个函数,用来取消订阅所用
    this.unSubscribe = store.subscribe(() => this.setState(store.getState()))
    // console.log(unSubscribe);
    // store.subscribe(() => this.setState({}))
  }

  componentWillUnmount() {
    // 取消订阅
    this.unSubscribe && this.unSubscribe()
  }

  addNum = () => {
    // 通知redux中state对象中的属性count要累加对应的数值
    store.dispatch(incrAction(10))
  }

  render() {
    let { count } = this.state
    // let { count } = store.getState()
    return (
      <div>
        <h3>{count}</h3>
        <button onClick={this.addNum}>累加数据</button>
      </div>
    );
  }
}

export default App;

src/store/action.js

export const incrAction = (n = 1) => ({
  type: 'incr',
  payload: n
})

src/store/index.js

// 创建一个数据仓库
import { createStore } from 'redux'
// redux调试工具
import { composeWithDevTools } from 'redux-devtools-extension';

import reducer from './reducer';

// 导出数据仓库
export default createStore(
  reducer,
  // window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
  composeWithDevTools()
)


src/store/reducer.js

import mutation from "./mutation"

// 数据reducer时,一定要给state有一个初始数据,此数据就是redux中统一数据源
const initState = {
  count: 100
}

// state只能通过reducer纯函数来修改,不是直接修改state数据,返回一个新的state
const reducer = (state = initState, { type, payload }) => {
  if (mutation[type]) {
    // 第1次它要初始化,它有一个默认的 dispatch操作@@INIT动作,
    // 它无需开发者去处理,所以要判断,去除
    // 当前的操作它存在
    return mutation[type](state, payload)
  }
  return state
}

export default reducer


src/store/mutation.js

// mutation操作
const mutation = {
  incr(state, data) {
    return {
      ...state,
      count: state.count + data
    }
  }
}

export default mutation



react-redux

npm i -S react-redux  redux

src/index.js

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

装饰器的写法:

在这里插入图片描述

下面是分析过程:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述



react-redux 拆分

在这里插入图片描述

在这里插入图片描述



使用异步中间件 redux-thunk

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述



code 图示版

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述



多人开发 模块化拆分

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述



code

在这里插入图片描述



index.js
import React from 'react';
import ReactDOM from 'react-dom';
// 根组件
import App from './App';

import { BrowserRouter as Router } from 'react-router-dom'

// redux
import { Provider } from 'react-redux'
import store from './store'

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



App.js
import React, { Component } from 'react';
import Films from './components/Films';

class App extends Component {
  render() {
    return (
      <div>
        <Films />
      </div>
    );
  }
}

export default App;



src\components\Films\index.jsx
import React, { Component } from 'react'
import connect from './connect';

@connect
class Films extends Component {

  componentDidMount() {
    this.props.addFilmAction()
  }

  render() {
    return (
      <div>
        <ul>
          {
            this.props.films.map(item => (
              <li key={item.filmId}>{item.name}</li>
            ))
          }
        </ul>
      </div>
    );
  }
}

export default Films;



src\store\index.js
import { createStore, applyMiddleware, combineReducers } from 'redux'
// combineReducers 它可以把多个reducer函数合并为一个大的reducer函数
// 引入中间件
import thunk from 'redux-thunk'
import { composeWithDevTools } from 'redux-devtools-extension'

// 引入拆分后的模块的reducer
import count from '@/reducer/count'
import film from '@/reducer/film'



// 把拆分后的小的reducer合并成为一个大的reducer
const reducer = combineReducers({
  // key:value
  // key的作用为:state的命名空间名称,在redux中只有state有命名空间限制,所以在redux中的type操作名称最好不要重名,重名它会多次执行
  // value就是小的redux纯函数
  count,
  film
}) 


export default createStore(
  reducer,
  composeWithDevTools(applyMiddleware(thunk))
)


src\reducer\count.js
import * as mutation from '@/mutation/countMutation'

const initState = {
  num: 100
}

const reducer = (state = initState, { type, data }) => {
  if (mutation[type]) {
    return mutation[type](state, data)
  }
  return state
}

export default reducer


src\reducer\film.js
import * as mutation from '@/mutation/filmMutation'

const initState = {
  films: []
}

const reducer = (state = initState, { type, data }) => {
  if (mutation[type]) {
    return mutation[type](state, data)
  }
  return state
}

export default reducer


src\mutation\countMutation.js
export const addNum = (state, data) => ({
  ...state,
  num: state.num + data
})


src\mutation\filmMutation.js
export const addFilm = (state, data) => ({
  ...state,
  films: [...state.films, ...data]
})


src\utils\http.js
import axios from 'axios'

// 得到一个新的请求实例
const instance = axios.create({
  // 请求超时时间
  timeout: 10000
});

// 响应拦截器
instance.interceptors.response.use(res => res.data, err => Promise.reject(err))

// get请求
export const get = (url, config = {}) => instance.get(url, config)
// post请求
export const post = (url, data = {}, config = {}) => instance.get(url, data, config)

export const put = (url, data = {}, config = {}) => instance.put(url, data, config)

export const del = (url, data = {}, config = {}) => instance.delete(url, data, config)



src\api\config\filmConfig.js
const config = {
  film: '/api/v1/getNowPlayingFilmList?cityId=110100&pageNum=1&pageSize=10'
}


export default config


src\api\filmApi.js
import { get } from '../utils/http'
import config from './config/filmConfig'

// 电影列表
export const getFilmsApi = () => get(config.film)


src\action\filmAction.js
import { getFilmsApi } from '@/api/filmApi'

/* // 对象中的方法,在没有使用中间件之前中能返回一个json对象,现在使用了中间件可以返回一个函数
export addFilm() {
  return async function (dispatch) {
    let ret = await getFilmsApi()
    dispatch({
      type: 'addFilm',
      data: ret.data.films
    })
  }
} */
// 对象中的方法,在没有使用中间件之前中能返回一个json对象,现在使用了中间件可以返回一个函数
export const addFilmAction = () => async dispatch => {
  let ret = await getFilmsApi()
  dispatch({
    type: 'addFilm',
    data: ret.data.films
  })
}





src\components\Films\connect.js
import { connect } from 'react-redux'
// 全部导入,它得到的是一个对象
import * as actions from '@/action/filmAction'


export default connect(state => {
  // console.log(state);
  // 使用了redux模块化,所以在获取state中的数据时要有命名空间属性
  return state.film
}, actions)



redux模块化自动导入

在这里插入图片描述



版权声明:本文为qq_14993591原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。