最近在学react,从github上下了个star比较多的项目来学习。遇到了下面这样的代码
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的内容。随便百度了下,发现没一个说得清楚这是干嘛的,使用场景是什么(也可能是我没找到说的清楚的)。
按照我刚学到的,我会这样写:
const mapDispatchToProps = (dispatch) => {
return {
handleLoginSuccess: (name) => {
dispatch(loginSuccessCreator(name))
}
}
};
那到底这两种写法有什么区别呢?看了下官方文档。直接贴代码:
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的话,我们需要这样写:
const mapDispatchToProps = (dispatch) => {
return {
addTodo: (text) => {
dispatch(TodoActionCreators.addTodo(text))
},
removeTodo: (id) => {
dispatch(TodoActionCreators.removeTodo(id))
}
}
};
使用bindActionCreators
const mapDispatchToProps = (dispatch) => {
return bindActionCreators(TodoActionCreators, dispatch);
};
回到最开头的代码
const mapDispatchToProps = (dispatch) => {
return {
handleLoginSuccess: bindActionCreators(loginSuccessCreator, dispatch),
};
};
这里loginSuccessCreator是个函数,官网文档的例子传入的是个对象,不过看源码函数也是能处理的(将函数返回)。
这里我就很纳闷了,既然你只有一个creator(loginSuccessCreator只返回一个action),使用bindActionCreators的意义何在?
本文纯属个人吐槽,感谢这莫名其妙的代码让我明白了bindActionCreators的使用场景。