react-redux的使用

文章目录

    • 认识 react-redux
    • react-redux 的使用
      • react-redux 相关 API
        • Provider
        • connect()
        • mapStateToprops()
        • mapDispatchToProps()
      • redux-thunk的使用
      • reducer 的合并
      • redux 调试工具的使用
      • 举例
        • 不使用 redux
        • 使用 redux
        • 使用 react-redux

认识 react-redux

react-redux 是一个 react 的插件库,它是专门用来简化 react 应用中使用 redux的

传送门

react-redux 的使用

react-redux 相关 API

Provider

让所有组件都可以得到 state 数据

<Provider store={store}>
   <App />
</Provider>

connect()

用于包装 UI 组件生成容器组件

export default connect(mapStateToProps, mapDispatchToProps)(Counter);

mapStateToprops()

将外部的数据(即state对象)转换为UI组件的标签属性

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

const mapDispatchToProps = (dispatch) => {
  return {
    increment: (value) => {
      dispatch(createIncrementAction(value));
    },
    decrement: (value) => {
      dispatch(createDecrementActio(value));
    }
  }
}

mapDispatchToProps()

将分发action的函数转换为UI组件的标签属性

const mapDispatchToProps = (dispatch) => {
  return {
    increment: (value) => {
      dispatch(createIncrementAction(value));
    },
    decrement: (value) => {
      dispatch(createDecrementActio(value));
    }
  }
}

传送门

redux-thunk的使用

处理异步编程的问题

store.js

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

let store = createStore(reducer, composeWithDevTools(applyMiddleware(thunk)));

export default store;
export const createIncrementAsyncAction = () => {
  return (dispatch) => {
    axios.get("http://localhost:3000/banner").then(res => {
      const data = res.data.data
      dispatch(createChangeBannersAction(data.banners));
    })
  }
}

reducer 的合并

import {combineReducers} from 'redux';
const reducer = composeEnhancers({
  counterInfo: counterReducer,
  bannersInfo: bannersReducer
});

redux 调试工具的使用

默认是不那个用的需要进行简答的处理,两种方法:

1、安装依赖包redux-devtools-extension,修改 store.js 文件

import { composeWithDevTools } from 'redux-devtools-extension'

const store = createStore(
  reducer,
  composeWithDevTools(applyMiddleware(thunk)) 
)

2、引入 composeEnhancers

import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import reducer from './reducer';
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
let store = createStore(reducer, composeEnhancers(applyMiddleware(thunk)));

export default store;

传送门

举例

实现一个简答的计数器,功能大致如下

react-redux的使用_第1张图片

不使用 redux

import React, { Component } from 'react';

class App extends Component {
  constructor() {
    super();
    this.state = {
      counter: 0
    }
  }

  render() {
    return (
      <div>
        <h2>当前计数:{this.state.counter}</h2>
        <select ref="selectRef">
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>
        <button onClick={() => {this.increment()}}>+</button>
        <button onClick={() => {this.decrement()}}>-</button>
        <button onClick={() => {this.incrementAsync()}}>一秒后再加</button>
      </div>
    );
  }

  increment() {
    const { value } = this.refs.selectRef;
    let { counter } = this.state;
    counter += Number(value);
    this.setState({
      counter
    });
  }

  incrementAsync() {
    setTimeout(() => {
      this.increment();
    }, 1000);
  }

  decrement() {
    const { value } = this.refs.selectRef;
    let { counter } = this.state;
    counter -= Number(value);
    this.setState({
      counter
    });
  }
}

export default App;

使用 redux

index.js

import React from "react";
import ReactDOM from "react-dom";

import App from "./App";
import store from "./store/store";

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

// 监听 state 的变化
store.subscribe(() => {
  ReactDOM.render(<App store={store}/>, document.getElementById("root"));
})

App.js

import React, { Component } from 'react';
import { createDecrementActio, createIncrementAction } from './redux/createActions'

class App extends Component {
  
  componentDidMount() {
    console.log(this.props.store);
  }

  render() {
    const { counter } = this.props.store.getState();
    return (
      

当前计数:{counter}

); } increment() { const store = this.props.store; let { value } = this.refs.selectNumberRef; store.dispatch(createIncrementAction(Number(value))); } incrementAsync() { const store = this.props.store; let { value } = this.refs.selectNumberRef; setTimeout(() => { store.dispatch({ type: 'incrementAsync', data: Number(value) }) }, 1000); } decrement() { const store = this.props.store; let { value } = this.refs.selectNumberRef; store.dispatch({ type: 'decrement', data: Number(value) }) } } export default App;

index.js

import React from "react";
import ReactDOM from "react-dom";

import App from "./App";
import store from "./redux/store";

ReactDOM.render(<Redux store={store}/>, document.getElementById("root"));

// 监听 state 的变化
store.subscribe(() => {
  ReactDOM.render(<Redux store={store}/>, document.getElementById("root"));
})

store 文件夹

store.js

import { createStore } from 'redux';
import reducer from './reducer';
// 创建 store
const store = createStore(reducer);

export default store;

reducer.js

import { INCREMENT, DECREMENT } from './actionTypes';

const defaultState = {
  counter: 1
}

function handleCounter(preState = defaultState, action) {
  console.log(action);
  let newState;
  switch (action.type) {
    case INCREMENT:
      newState = {
        counter: preState.counter + action.data
      };
      return newState;

    case 'incrementIfOdd':
      newState = {
        counter: preState.counter + action.data
      };
      return newState;

    case 'incrementAsync':
      newState = {
        counter: preState.counter + action.data
      };
      return newState;
    case DECREMENT:
      newState = {
        counter: preState.counter - action.data
      };
      return newState;
    default:
      return preState;
  }
}

export default handleCounter;

createActions.js

import { INCREMENT, DECREMENT, INCREMENTASYNC } from './actionTypes';
export const createIncrementAction = value => ({
  type: INCREMENT,
  data: value
})

export const createDecrementActio = value => ({
  type: DECREMENT,
  data: value
})


export const createIncrementAsyncAction = (value, delay) => {
  return (dispatch) => {
    setTimeout(() => {
      dispatch(createIncrementAction(value, delay));
    }, delay);
  }
}

actionTypes.js

export const INCREMENT = 'increment';
export const DECREMENT = 'decrement';
export const INCREMENTASYNC = 'incrementAsync';

使用 react-redux

index.js

import React from "react";
import ReactDOM from "react-dom";

import App from "./App";
import store from "./store/store";


import { Provider } from "react-redux";

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

将 App.js 进行拆分

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pA5syu64-1597136908932)(C:\Users\27857\Desktop\QQ截图20200811153735.png)]

counter.jsx

import React, { Component } from 'react';

class Counter extends Component {
  
  componentDidMount() {
    console.log(this.props)
  }

  render() {
    return (
      <div>
        <h2>当前计数:{this.props.counter}</h2>
        <select ref="selectNumberRef">
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>
        <button onClick={() => {this.increment()}}>+</button>
        <button onClick={() => {this.decrement()}}>-</button>
        <button onClick={() => {this.incrementIfOdd()}}>odd</button>
        <button onClick={() => {this.incrementAsync()}}>async</button>
      </div>
    );
  }

  increment() {
    let { value } = this.refs.selectNumberRef;
    this.props.increment(Number(value));
  }

 
  incrementAsync() {
    let { value } = this.refs.selectNumberRef;
    this.props.incremenAsync(Number(value), 1000);
    
  }

  decrement() {
    let { value } = this.refs.selectNumberRef;
    this.props.decrement(Number(value));
  }
}

export default Counter;

counter_container.js

import { connect } from 'react-redux';
import Counter from '../components/counter';
import { createDecrementActio, createIncrementAction, createIncrementAsyncAction } from '../redux/createActions';

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

const mapDispatchToProps = (dispatch) => {
  return {
    increment: (value) => {
      dispatch(createIncrementAction(value));
    },
    decrement: (value) => {
      dispatch(createDecrementActio(value));
    }
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Counter);

可以对上面进行简单优化

export default connect(
  state =>({
    counter: state.counter
  }),
  {
    increment: createIncrementAction,
    decrement: createDecrementActio,
    incremenAsync: createIncrementAsyncAction
  }
)(Counter)

connect 函数的作用

function connect(fn) {
  return (value) => {dispatch(fn(value))}
}

你可能感兴趣的:(react)