react-redux 之bindActionCreators

最近在學react,從github上下了個star比較多的項目來學習。遇到了下面這樣的代碼react

export const loginSuccessCreator = (userName) => {
  return {type: 'LOGIN_SUCCESS', payload: userName};
};

const initState = {
  login: false,  // 是否已登陸
  userName: '未登陸', // 登陸後的用戶名
};

const reducer = (state = initState, action = {}) => {
  switch (action.type) {
    case 'LOGIN_SUCCESS':
      return {...state, login: true, userName: action.payload};
    default:
      return state;
  }
};

export default {initState, reducer};
const mapDispatchToProps = (dispatch) => {
  return {
    handleLoginSuccess: bindActionCreators(loginSuccessCreator, dispatch),
  };
};

// 不須要從state中獲取什麼, 因此傳一個null
export default connect(null, mapDispatchToProps)(Login);

當時我尚未去官方文檔瞭解關於bindActionCreators的內容。隨便百度了下,發現沒一個說得清楚這是幹嗎的,使用場景是什麼(也多是我沒找到說的清楚的)。git

按照我剛學到的,我會這樣寫:github

const mapDispatchToProps = (dispatch) => {
  return {
    handleLoginSuccess: (name) => {
      dispatch(loginSuccessCreator(name))
    }
  }
};

那到底這兩種寫法有什麼區別呢?看了下官方文檔。直接貼代碼:redux

TodoActionCreators.js函數

export function addTodo(text) {
  return {
    type: 'ADD_TODO',
    text
  }
}
​
export function removeTodo(id) {
  return {
    type: 'REMOVE_TODO',
    id
  }
}

SomeComponent.js學習

import { Component } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
​
import * as TodoActionCreators from './TodoActionCreators'
console.log(TodoActionCreators)
// {
//   addTodo: Function,
//   removeTodo: Function
// }
​
class TodoListContainer extends Component {
  constructor(props) { 
    super(props);
​
    const {dispatch} = props;
​
    // Here's a good use case for bindActionCreators:
    // You want a child component to be completely unaware of Redux.
    // We create bound versions of these functions now so we can
    // pass them down to our child later.
​
    this.boundActionCreators = bindActionCreators(TodoActionCreators, dispatch)
    console.log(this.boundActionCreators)
    // {
    //   addTodo: Function,
    //   removeTodo: Function
    // }
  }
​
  componentDidMount() {
    // Injected by react-redux:
    let { dispatch } = this.props
​
    // Note: this won't work:
    // TodoActionCreators.addTodo('Use Redux')
​
    // You're just calling a function that creates an action.
    // You must dispatch the action, too!
​
    // This will work:
    let action = TodoActionCreators.addTodo('Use Redux')
    dispatch(action)
  }
​
  render() {
    // Injected by react-redux:
    let { todos } = this.props
​
    return <TodoList todos={todos} {...this.boundActionCreators} />
​
    // An alternative to bindActionCreators is to pass
    // just the dispatch function down, but then your child component
    // needs to import action creators and know about them.
​
    // return <TodoList todos={todos} dispatch={dispatch} />
  }
}
​
export default connect(
  state => ({ todos: state.todos })
)(TodoListContainer)

針對TodoActionCreators不使用bindActionCreators的話,咱們須要這樣寫:this

const mapDispatchToProps = (dispatch) => {
  return {
    addTodo: (text) => {
      dispatch(TodoActionCreators.addTodo(text))
    },
    removeTodo: (id) => {
      dispatch(TodoActionCreators.removeTodo(id))
    }
  }
};

使用bindActionCreatorsspa

const mapDispatchToProps = (dispatch) => {
  return bindActionCreators(TodoActionCreators, dispatch);
};

回到最開頭的代碼code

const mapDispatchToProps = (dispatch) => {
  return {
    handleLoginSuccess: bindActionCreators(loginSuccessCreator, dispatch),
  };
};

這裏loginSuccessCreator是個函數,官網文檔的例子傳入的是個對象,不過看源碼函數也是能處理的(將函數返回)。component

這裏我就很納悶了,既然你只有一個creator(loginSuccessCreator只返回一個action),使用bindActionCreators的意義何在?

本文純屬我的吐槽,感謝這莫名其妙的代碼讓我明白了bindActionCreators的使用場景。

相關文章
相關標籤/搜索