ReactCollect icon indicating copy to clipboard operation
ReactCollect copied to clipboard

关于react-redux中, connect方法的mapStateToProps和mapDispatchToProps

Open ckinmind opened this issue 8 years ago • 9 comments

问题:

  1. mapStateToProps和mapDispatchToProps的写法
  2. mapStateToProps和mapDispatchToProps这两个参数是必须的吗
  3. mapStateToProps和mapDispatchToProps各自代表什么意思

ckinmind avatar Jan 23 '17 14:01 ckinmind

1)写法

import { connect } from 'react-redux'
import { toggleTodo } from '../actions'
import TodoList from './TodoList'

const getVisibleTodos = (todos, filter) => {
  switch (filter) {
    case 'SHOW_ALL':
      return todos;
    case 'SHOW_COMPLETED':
      return todos.filter(t => t.completed);
    case 'SHOW_ACTIVE':
      return todos.filter(t => !t.completed);
    default:
      throw new Error('Unknown filter: ' + filter)
  }
};

const mapStateToProps = (state) => ({
  todos: getVisibleTodos(state.todos, state.visibilityFilter)
});

const mapDispatchToProps =  ({
  onTodoClick: toggleTodo
});

const TodoListContainer = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList);

export default TodoListContainer

ckinmind avatar Jan 24 '17 12:01 ckinmind

2) 不是必须的(可以都不传,也可以只传一个)

import React from 'react'
import { connect } from 'react-redux'
import { addTodo } from '../actions'


/**
 * 这里用了let没用const,因为下面有 AddTodo = connect()(AddTodo)
 */
const AddTodo = ({dispatch}) => {
  let input;
  return (
    <div>
      <form onSubmit={e => {
        e.preventDefault();
        if (!input.value.trim()) {
          return
        }
          dispatch(addTodo(input.value));
        input.value = ''
      }}>
        <input ref={node => {
          input = node
        }} />
        <button type="submit">
          Add Todo
        </button>
      </form>
    </div>
  )
};

const AddTodoContainer= connect()(AddTodo);
export default AddTodoContainer;

经过测试发现如果不在mapStateToProps和mapDispatchToProps中指定要传入UI组件AddTodo的数据和回调函数,则AddTodo组件只能访问到dispatch这个store中的api, 用于触发action,我记得redux中有提到可以在任何地方dispatch

ckinmind avatar Jan 24 '17 12:01 ckinmind

参考资料:React 实践心得:react-redux 之 connect 方法详解

connect 详解
究竟 connect 方法到底做了什么,我们来一探究竟。
首先看下函数的签名:
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
connect() 接收四个参数,它们分别是 mapStateToProps , mapDispatchToProps , mergeProps 和 options 
mapStateToProps(state, ownProps) : stateProps
这个函数允许我们将 store 中的数据作为 props 绑定到组件上
函数的第二个参数 ownProps ,是 MyComp 自己的 props

mapDispatchToProps(dispatch, ownProps): dispatchProps
connect 的第二个参数是 mapDispatchToProps ,它的功能是,将 action 作为 props 绑定到 MyComp 上

Redux 本身提供了 bindActionCreators 函数,来将 action 包装成直接可被调用的函数

疑问:bindActionCreators是什么?

ckinmind avatar Jan 24 '17 15:01 ckinmind

参考资料:阮一峰;Redux 入门教程(三):React-Redux 的用法

关于mapStateToProps

  1. mapStateToProps是一个函数
  2. 作为函数,mapStateToProps执行后应该返回一个对象,里面的每一个键值对就是一个映射
  3. mapStateToProps会订阅 Store,每当state更新的时候,就会自动执行,重新计算 UI 组件的参数,从而触发 UI 组件的重新渲染
  4. mapStateToProps的第一个参数总是state对象,还可以使用第二个参数,代表容器组件的props对象
  5. 使用ownProps作为第二个参数后,如果容器组件的参数发生变化,也会引发 UI 组件重新渲染
  6. connect方法可以省略mapStateToProps参数,那样的话,UI 组件就不会订阅Store,就是说 Store 的更新不会引起 UI 组件的更新

关于mapDispatchToProps

  1. mapDispatchToProps是connect函数的第二个参数,用来建立 UI 组件的参数到store.dispatch方法的映射
  2. 也就是说,它定义了哪些用户的操作应该当作 Action,传给 Store。它可以是一个函数,也可以是一个对象
  3. 如果mapDispatchToProps是一个函数,会得到dispatch和ownProps(容器组件的props对象)两个参数
  4. 如果mapDispatchToProps是一个对象,它的每个键名也是对应 UI 组件的同名参数,键值应该是一个函数,会被当作 Action creator ,返回的 Action 会由 Redux 自动发出

ckinmind avatar Jan 25 '17 07:01 ckinmind

bindActionCreators() 可以自动把多个 action 创建函数 绑定到 dispatch() 方法上。 https://cn.redux.js.org/docs/basics/Actions.html

ricocai avatar Feb 23 '18 02:02 ricocai

@ricocai 这个已经是很久以前的issue了,我现在也不用redux,推荐mobx

ckinmind avatar Feb 23 '18 02:02 ckinmind

connect 是一个科里化函数??

plh97 avatar Nov 24 '18 05:11 plh97

@pengliheng 是一个高阶函数

BigFaceWangCY avatar Jan 07 '19 03:01 BigFaceWangCY

const mapDispatchToProps = (dispatch, ownProps) => {
    return {
        setSignIn: (payload) => {
            dispatch({type: 'note/sign_In', payload})
        }
    }
}
export default connect(mapDispatchToProps)(Info)  

我只传一个的时候,为啥会报这个错误啊 加上connect中加上这个mapStateToProps则会正常运行了

用的是dvs image

anran-world avatar Aug 14 '21 08:08 anran-world