redux react-redux基础

redux

一、 基础

1.  import

import { createStore } from 'redux';

const store = createStore(fn);

2.  getState

//获取当前时刻的state

const state = store.getState();

3.   action

//action对象,type必需

const action = {  type: 'ADD_TODO',  payload: 'Learn Redux'};

4.  action creator

//生成action creator,方便action书写

const ADD_TODO = ‘添加 TODO’;

function addTodo(text) {
  return {
    type: ADD_TODO,
    text
  }
}

const action = addTodo('Learn Redux');

5.  dispatch发出action

//View 发出 Action 的唯一方法dispatch

store.dispatch(addTodo('Learn Redux'));

6.  reducer返回新state

//接受 Action 和当前 State 作为参数,返回一个新的 State

const reducer = function (state, action) {  // …  return new_state;};

const defaultState = 0;

const reducer = (state = defaultState, action) => {
  switch (action.type) {
    case 'ADD':
      return state + action.payload;
    default:
       return state;
  }};
const state = reducer(1, {  type: 'ADD',  payload: 2});

7.  自动调用reducer

import { createStore } from 'redux';

const store = createStore(reducer);

上面代码中,createStore接受 Reducer 作为参数,生成一个新的 Store。以后每当store.dispatch发送过来一个新的 Action,就会自动调用 Reducer,得到新的 State。

为什么这个函数叫做 Reducer 呢?因为它可以作为数组的reduce方法的参数。请看下面的例子,一系列 Action 对象按照顺序作为一个数组。

const actions = [
{ type: 'ADD', payload: 0 },
{ type: 'ADD', payload: 1 },
{ type: 'ADD', payload: 2 }
];
const total = actions.reduce(reducer, 0); // 3

8.   subscribe监听

//Store 允许使用store.subscribe方法设置监听函数,一旦 State 发生变化,就自动执行这个函数。

import { createStore } from 'redux';

const store = createStore(reducer);

store.subscribe(listener);

store.subscribe方法返回一个函数,调用这个函数就可以解除监听。

let unsubscribe = store.subscribe(() =>
  console.log(store.getState())
);

unsubscribe();

9.   Store 的实现

  • getState()
  • dispatch()
  • subscribe()
import { createStore } from 'redux';

let { subscribe, dispatch, getState } = createStore(reducer);

createStore方法还可以接受第二个参数,表示 State 的最初状态。这通常是服务器给出的。

let store = createStore(todoApp, window.STATE_FROM_SERVER)

示例:

const createStore = (reducer) => {
  let state;
  let listeners = [];
   const getState = () => state;
   const dispatch = (action) => {
    state = reducer(state, action);
    listeners.forEach(listener => listener());
  };
   const subscribe = (listener) => {
    listeners.push(listener);
    return () => {
      listeners = listeners.filter(l => l !== listener);
    }
  };
   dispatch({});
   return { getState, dispatch, subscribe };
};

10.reducer拆分

可以把所有子 Reducer 放在一个文件里面,然后统一引入。

import { combineReducers } from 'redux'

import * as reducers from './reducers'

const reducer = combineReducers(reducers)

二、 中间件

1.  用法

日志中间件,就有现成的redux-logger模块

import { applyMiddleware, createStore } from 'redux';
import createLogger from 'redux-logger';
const logger = createLogger();
 const store = createStore(
  reducer,
  applyMiddleware(logger)
);

createStore有三个参数,中间件有次序要求,比如,logger就一定要放在最后
const store = createStore(
  reducer, 
  initial_state,
  applyMiddleware(thunk, promise, logger)
);

applyMiddlewares是 Redux 的原生方法,作用是将所有中间件组成一个数组,依次执行,最后执行store.dispatch。

2.  异步操作中间件

reduc-thunk

redux-thunk中间件,改造store.dispatch,使得后者可以接受函数作为参数

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducer from './reducers'; // Note: this API requires redux@>=3.1.0
const store = createStore(  reducer,  applyMiddleware(thunk));

fetchPosts是一个Action Creator(动作生成器),返回一个函数.

const fetchPosts = postTitle => (dispatch, getState) => {
  dispatch(requestPosts(postTitle));
  return fetch(`/some/API/${postTitle}.json`) 
   .then(response => response.json())
    .then(json => dispatch(receivePosts(postTitle, json)));
  };
}; 
// 使用方法一
store.dispatch(fetchPosts('reactjs'));
// 使用方法二
store.dispatch(fetchPosts('reactjs')).then(() =>  console.log(store.getState()));

redux-promise

import { createStore, applyMiddleware } from 'redux';
import promiseMiddleware from 'redux-promise';
import reducer from './reducers'; 
const store = createStore(
  reducer,
  applyMiddleware(promiseMiddleware)
);

这时,Action Creator 有两种写法。写法一,返回值是一个 Promise 对象。

const fetchPosts =

(dispatch, postTitle) => new Promise(function (resolve, reject) {

dispatch(requestPosts(postTitle));

return fetch(`/some/API/${postTitle}.json`)

.then(response => {

type: 'FETCH_POSTS',

payload: response.json()

});

});

写法二,Action 对象的payload属性是一个 Promise 对象。这需要从redux-actions模块引入createAction方法,并且写法也要变成下面这样。

import { createAction } from 'redux-actions';


class AsyncApp extends Component {

componentDidMount() {

const { dispatch, selectedPost } = this.props

// 发出同步 Action

dispatch(requestPosts(selectedPost));

// 发出异步 Action

dispatch(createAction(

'FETCH_POSTS',

fetch(`/some/API/${postTitle}.json`)

.then(response => response.json())

));

}

三、 react-redux

React-Redux 将所有组件分成两大类:UI 组件(presentational component)和容器组件(container component)

1.  connect

import { connect } from 'react-redux'
const VisibleTodoList = connect(  mapStateToProps,  mapDispatchToProps)(TodoList)
mapStateToProps

负责输入逻辑,即将state映射到 UI 组件的参数(props),

mapDispatchToProps

负责输出逻辑,即将用户对 UI 组件的操作映射成 Action。

2.  provider

React-Redux 提供Provider组件,可以让容器组件拿到state

import { Provider } from 'react-redux'
import { createStore } from 'redux'
import todoApp from './reducers'
import App from './components/App' 
let store = createStore(todoApp); 
render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

3.   React-Router 路由库

const Root = ({ store }) => (
  <Provider store={store}>
    <Router>
      <Route path="/" component={App} />
    </Router>
  </Provider>
);