Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

redux 快速入门 #15

Open
eyasliu opened this issue Jun 20, 2016 · 0 comments
Open

redux 快速入门 #15

eyasliu opened this issue Jun 20, 2016 · 0 comments

Comments

@eyasliu
Copy link
Owner

eyasliu commented Jun 20, 2016

应用中所有的 state 都以一个对象树的形式储存在一个单一的 store 中。惟一改变 state 的办法是触发 action,一个描述发生什么的对象。为了描述 action 如何改变 state 树,你需要编写 reducers。

三大原则

  • 单一数据源:整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。
  • State 是只读的: 惟一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。
  • 使用纯函数来执行修改: 为了描述 action 如何改变 state tree ,你需要编写 reducers

基础

action

Action 是把数据从应用传到 store 的有效载荷。它是 store 数据的唯一来源。一般使用 store.dispatch() 将action 传到store

const action = {
  type: 'ADD_TODO',
  text: 'Build my first Redux app'
}

store.dispatch(action)

一个action必须有type字段,描述action做的事情,其他字段都为可选项,是action携带的数据,只作为传递数据用途。

action 创建函数

Action 创建函数 就是生成 action 的方法。可以简单的理解为调用这个函数就会创建action并且自动调用store.dispatch()。当我们使用react-redux工具时,可以自动绑定dispatch,所以函数可以简化为这样:

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

// 在组件中调用,自动dispatch
this.props.addTodo('test task')

redux会dispatch函数的返回值

reducer

action 只是描述了有事情发生了这一事实,reducer根据action的描述怎么去更新状态。reducer就是一个纯函数,接收旧的state和action,返回新的state。使用函数默认值设置初始状态。

function todo(state = {todos: []}, action){
  switch(action.type){
    case 'ADD_TODO':
      return {
        ...state,
        todos: [
          ...state.todos,
          {
            id: state.todos.length + 1,
            text: action.text
          }
        ]
      }
    default:
      return state;
  }
}

注意:永远不要在reducer做这些事

  • 修改传入参数

  • 执行有副作用操作,如api请求和路由跳转

  • 调用非纯函数

  • 不修改state,直接返回一个新对象state

    谨记 reducer 一定要保持纯净。只要传入参数相同,返回计算得到的下一个 state 就一定相同。没有特殊情况、没有副作用,没有 API 请求、没有变量修改,单纯执行计算

拆分 reducer

应用一旦复杂了,reduer会非常长,为了更好的模块化管理,拆分成多个小reducer,然后合并。Redux 提供了 combineReducers() 工具类合并reducer。但只能有一个根reducer,相当于react组件只有一个根标签。

import { combineReducers } from 'redux';

const todoCrud = (state, action) => {}
const todoVisable = (state, action) => {}

const todo = combineReducers({
  crud: todoCrud,
  visable: todoVisable
})

export default todo;

store

action 来描述“发生了什么”,reducers 来根据 action 更新 state 。Store就是把他们联系到一起的对象。Redux 应用只有一个单一的 store

  • 维持应用的 state;
  • 提供 getState() 方法获取 state;
  • 提供 dispatch(action) 方法更新 state;
  • 通过 subscribe(listener) 注册监听器;
  • 通过 subscribe(listener) 返回的函数注销监听器。

创建store

redux 提供 createStore() 工具创建store,接收根reducer作为参数

import {createStore} from 'redux';
import rootReducer from './reducers';
const store = createStore(rootReducer)

搭配react

Redux 和 React 之间没有关系。Redux 支持 React、Angular、Ember、jQuery 甚至纯 JavaScript。他只是一个状态管理工具而已。

redux与react搭配使用react-redux工具。

Provider

<Provider /> 包围需要使用redux状态的组件。如根组件。provider 需要传递 store 进去。

import { render } from 'react-dom';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import App from './containers/App';
import todoApp from './reducers';

let store = createStore(todoApp);

let rootElement = document.getElementById('root')
render(
  <Provider store={store}>
    <App />
  </Provider>,
  rootElement
)

connect && bindActionCreators

在Provider包围的范围内,通过 react-redux 提供的 connect() 方法将包装好的组件连接到Redux。传入组件需要的状态与action 生成函数。

bindActionCreators 可以将普通的函数自动绑定变为 action生成函数

import {connect, bindActionCreators} from 'redux';
import {addTodo} from './actions';

class App extends React.Component{
  handlerClick(e){
    this.props.todos // 来自于redux的 state.todos
    this.props.addTodo('this is my task') // 调用 action 生成函数
  }
  render(){
    return <div onClick={this.handlerClick}></div>
  }
}

// 将 reudx 的状态传递给组件,可在组件的props获取
function mapStateToProps(state){
  return {
    todos: state.todos
  }
}
// 将普通函数绑定转化为action生成器
function mapDispatchToProps(dispatch){
  return bindActionCreators({addTodo}, dispatch);
}

// 连接
export default connect(mapStateToProps, mapDispatchToProps)(App)

我们可以使用 es7 的 decorator 简化代码书写。

@connect(
  state => ({todos: state.todos})
  disatch => bindActionCreators({todos, dispatch})
)
export default class App extends React.Component{}

中间件

在 action 被发起之后,到达 reducer 之前可以使用中间件处理action。

异步action

redux-thunk 是处理异步action的redux中间件,它的所有代码如下

function createThunkMiddleware(extraArgument) {
  return ({ dispatch, getState }) => next => action => {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }

    return next(action);
  };
}

如果action是函数,那就需要显示调用 dispatch 才能真正触发action,使用方法如下

const getTodo(){
  return dispatch => {
    request.get(url).end((err, res) => {
      dispatch({
        type: 'GET_TODO',
        data: res.body
      })
    })
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant