最近在學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的使用場景。