Redux

245 阅读3分钟

Redux

Redux = Flux + Reducer

  1. stroe/index.js
import { createStore } from 'redux'
import reducer from './reducer'
const store = createStore()
export default store
  1. reducer.js

reducer是一个纯函数,reducer可以接收state但是觉得不能修改state

import {CHANGE_SOMETHING} from './actionTypes.js'
const defaultState = {
  inputValue: '',
  list: [1, 3]
}
export default (state = defaultState, action) => {
  if(action.type === CHANGE_SOMETHING){
      const newState = JSON.parse(JSON.Stringify(state))
      newState.inputValue  = action.value
      return newState
  }
  return state
}
  1. 组件中的使用
import store from './store'
constructor(){
  this.state = store.getState() //获取state
  this.handleStroeChange = this.handleStroeChange.bind(this)
  store.subscribe(this.handleStroeChange)  
}
handleStroeChange(e){
    this.setState(store.getState())
}
  1. 组件中派发action
import {CHANGE_SOMETHING} from './actionTypes.js'
import {getInputChangeAction} from './actionCreators.js'
import store from './store'
const action = getInputChangeAction('val')
store.dispatch(action)
  1. actionTypes.js

其实这样已经能够使用redux了,但是为了避免因为拼写错误导致代码出错,并且这种错误又不容易发现(因为没有细致的提示),我们将actiontype提取为常量。

export const CHANGE_SOMETHING = 'change_something'
  1. actionCreators.js
import {CHANGE_SOMETHING} from './actionTypes.js'
export const getInputChangeAction = (val)=>({
  type:CHANGE_SOMETHING,
  value:val
})
  • store是唯一的
  • 只有store可以改变自己的内容
  • reducer是个纯函数

Redux DevTools

安装Redux DevTools插件

配置Redux DevTools插件

const store = createStore(reducer,
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())

redux中间件

中间件是只action和store之间

Redux-thunk

使用的Redux-thunk之后,要结合redux-devtools-extension重新配置一下Redux DevTools。

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

const composeEnhancers =
  typeof window === 'object' &&
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
    ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
    }) : compose
const enhancer = composeEnhancers(
  applyMiddleware(thunk)
)
const store = createStore(reducer, enhancer)
export default store

Redux-thunk的使用

  1. actionCreators里面创建的actionCreator的返回值是函数
export const getTodoList = () => {
  return (dispatch) => {
    axios.get('./list.json').then((res) => {
      // const data = res.data

    }, () => {
    	const data = ['学英语']
    	const action = initListAction(data)
    	dispatch(action)
    })
  }
}
  1. 在componentDidMount派发action后,第一步中的函数会自动执行,这个时候就可以把接口请求从视图中提取出来
componentDidMount () {
  // axios.get('./todolist').then((resp) => {
  // 	const data = resp.data
  // 	const action = initListAction(data)
  // }, () => {
  // })
  var action = getTodoList()
  store.dispatch(action)
}

Redux-saga

使用的Redux-saga之后,要重新配置一下Redux DevTools。

import { createStore, applyMiddleware, compose } from 'redux'
import reducer from './reducer'
import createSagaMiddleware from 'redux-saga'
import todoSagas from './sagas'

const sagaMiddleware = createSagaMiddleware()

const composeEnhancers =
  typeof window === 'object' &&
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
    ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
    }) : compose
    
const enhancer = composeEnhancers(
  applyMiddleware(sagaMiddleware)
)
const store = createStore(reducer, enhancer)
sagaMiddleware.run(todoSagas)
export default store

Redux-saga的使用

  1. 创建saga.js文件
import { call, put, takeEvery, takeLatest } from 'redux-saga/effects'
import { GET_TODO_LIST } from './actionTypes'
import { initListAction } from './actionCreators'
import axios from './axios'

function * getTodoList () {
  // axios.get('./list').then((resp) => {
  // 	const data = resp.data
  // 	const action = initListAction(data)
  // 	// 把数据更新到store
  // 	put(action)
  // })
  try {
  	const res = yield axios.get('./list')
  	const action = initListAction(res.data)
  	yield put(action)
  } catch (e) {
  	ConstantSourceNode
  }
}

function * mySaga () {
  yield takeEvery(GET_TODO_LIST, getTodoList)
}
export default mySaga
  1. 当在组件中通过dispatch()方法派发action的时候,不仅reducer中会接收到修改信息,saga中也会接收到,这样就可以将异步请求放在saga.js文件中统一管理。
//actionCreators.js
export const getTodoList = () => ({
  type: GET_TODO_LIST
})
//组件中
componentDidMount () {
  var action = getTodoList()
  store.dispatch(action)
}

React-redux

React-redux的使用

  1. 安装react-redux
yarn add react-redux
  1. 引用组件处的使用
import React from 'react'
import ReactDOM from 'react-dom'
import TodoList from './react-redux/TodoList'
import store from './react-redux/store'
import { Provider } from 'react-redux'
const 	App = (
  <Provider store={store}>
    <TodoList />
  </Provider>
)
ReactDOM.render(App, document.getElementById('root'))
  1. 组件内部的使用
import React, { Component } from 'react'
import { connect } from 'react-redux'
class TodoList extends Component {
  constructor (props) {
    super(props)
  }
  render () {
  	return (<div>
      <div>
      <input value={this.props.inputValue} onChange={this.props.hanleInputChange} />
      <button }>提交</button>
    </div>
      <ul>
      <li>dell</li>
    </ul>
  		</div>)
  }
  hanleInputAdd () {

  }
}
//
const mapStateToProps = (state) => {
  return {
  	inputValue: state.inputValue
  }
}
// store.dispatch方法挂载到store上
const mapDispatchToProps = (dispatch) => {
  return {
  	  hanleInputChange (e) {
  	  	const inputValue = e.target.value
  	  	const action = {
  	  		type: 'change_input_value',
  	  		value: inputValue
  	  	}
  	  	dispatch(action)
    }
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoList)