react-redux文档翻译

英文文档链接

API


使得层级之下的组件可以通过connect()函数访问到Redux store。通常,如果你不将父组件或者根组件用组件包裹起来的话,你是不可以使用connect()函数的。

Props

  • store (Redux Store): 应用中的单一数据源
  • children (ReactElement) :你的根组件

Example

Vanilla React
ReactDOM.render(
  
    
  ,
  rootEl
)
React Router
ReactDOM.render(
  
    
      
        
        
      
    
  ,
  document.getElementById('root')
)

connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])

将一个React组件连接到Redux store上去。connectconnectAdvanced的一层包装,对外提供了一套对于大多数开发情况下方便的API。
它并不更改传入的组件,而是返回一个新的、连接到store的组件共你使用。

Arguments

  • [mapStateToProps(state, [ownProps]): stateProps] (Function):如果这个参数指定了,这个新组件将会订阅store的更新。这意味着每次store更新,mapStateToProps将会被调用。mapStateToProps的结果是一个plain object,这个结果会和组件的props融合为新的props。如果你不想订阅store的更新,传入null或者undefined。

    如果你的mapStateToProps传入了两个参数,那么调用它时,store将会作为第一个参数,connected component的props将会作为第二个参数,并且也会重新触发,如果判定机制——浅相等比较判断组件接收到新的props。

    注意:在你需要对渲染性能有更多的控制的情况下,mapStateToProps也可以返回一个函数。在这种情况下,那个返回的函数将被特定的组件作为mapStateTOProps。这使得你可以完成单一实例记忆化(per-instance memoization)You can refer to #279 and the tests it adds for more details. 大多数应用不需要用到它。

    mapStateToProps接受一个store参数时,它将返回一个对象,这个对象将作为组建的props。我们通常将其称作selector,Use reselect to efficiently compose selectors and compute derived data.

  • [mapDispatchToProps(dispatch, [ownProps]): dispatchProps] (Object or Function):如果传入的是object,每一个其中的函数都应该是一个Redux action creator。一个拥有同样的函数的对象将会融合入组件的props,但不同的是这个对象的每个action creator将会作为dispatch的参数,这样它们就可以直接执行。

    如果传入的是一个函数,那么这个函数将会接受dispatch作为它的第一个参数。It’s up to you to return an object that somehow uses dispatch
    to bind action creators in your own way. (Tip: you may use the bindActionCreators()
    helper from Redux.)

    如果你的mapDispatchToProps传入了两个参数,那么dispatch将作为第一个参数,被连接的组件传入的props将作为第二个参数。每当组将接收到新的参数时,这个函数都将被触发。

    如果你不指定mapDispatchToProps参数,那么默认的mapDispatchToProps实现会将dispatch作为props连接的组件。

    Note: in advanced scenarios where you need more control over the rendering performance, mapDispatchToProps()
    can also return a function. In this case, that function will be used as mapDispatchToProps()
    for a particular component instance. This allows you to do per-instance memoization. You can refer to #279 and the tests it adds for more details. Most apps never need this.

  • [mergeProps(stateProps, dispatchProps, ownProps): props] (Function):如果这个函数指定了,那么传入这个函数的前两个参数分别为mapStateToProps(), mapDispatchToProps()的执行结果,第三个参数为组件自身的props。这个函数将会返回一个plain object,这个结果将成为被包裹组件的props。你也许可以用这个回调函数,根据组件的 props 来筛选部分的 state 数据,或者把 props 中的某个特定变量与 action creator 绑定在一起。如果你省略这个参数,默认情况下返回 Object.assign({}, ownProps, stateProps, dispatchProps)的结果。

  • [options] (Object):如果指定这个参数,可以进一步定制connector的行为。除了connectAdvanced()可以传入的选项之外,connect()还可以接收以下的额外选项。

    • [pure](Boolean):如果为true,当相关的state/props的相等判断机制判断其没有发生变化时,connect()将会避免组建的重新render()以及mapStateToProps, mapDispatchToProps, mergeProps的调用,前提是该组件是一个“纯”组件,即该组件不依赖于任何外部的输入和内部的state,只依赖于props和从connect()函数获取到的store的数据。默认值为true。
    • [areStatesEqual] (Function): When pure, compares incoming store state to its previous value. Default value: strictEqual (===)
    • [areOwnPropsEqual] (Function): When pure, compares incoming props to its previous value. Default value: shallowEqual
    • [areStatePropsEqual] (Function): When pure, compares the result of mapStateToProps to its previous value. Default value: shallowEqual
    • [areMergedPropsEqual] (Function): When pure, compares the result of mergeProps to its previous value. Default value: shallowEqual
    • [storeKey] (String): The key of the context from where to read the store. You probably only need this if you are in the inadvisable position of having multiple stores. Default value: 'store'
mapStateToProps和mapDispatchToProps函数的元数(arity,可以理解为函数长度)决定了它们是否能接收到ownProps作为第二个参数。

注意:如果定义一个包含强制性参数函数(这个函数的长度为 1)时,ownProps不会传到 mapStateToPropsmapDispatchToProps 中。举个例子,如下这样定义一个函数时将不会接收到 ownProps 作为第二个参数。

function mapStateToProps(state) {
  console.log(state); // state
  console.log(arguments[1]); // undefined
}
//因为这个函数有一个参数有默认值,所以这个函数的长度仍然为1
const mapStateToProps = (state, ownProps = {}) => {
  console.log(state); // state
  console.log(ownProps); // undefined
}

当函数没有强制性的参数或两个参数时将接收到 ownProps

const mapStateToProps = (state, ownProps) => {
  console.log(state); // state
  console.log(ownProps); // ownProps
}
function mapStateToProps() {
  console.log(arguments[0]); // state
  console.log(arguments[1]); // ownProps
}
const mapStateToProps = (...args) => {
  console.log(args[0]); // state
  console.log(args[1]); // ownProps
}
Optimizing(优化) connect when options.pure is true

options.puretrue的时候,connect将执行几个相等检测,以此避免不必要的mapStateToProps, mapDispatchToProps, mergeProps调用,最终导致render()。这些相等检测包括areStatesEqual, areOwnPropsEqual, areStatePropsEqual, 和areMergedPropsEqual。尽管默认参数可能适合于99%的场景,但是出于性能或者其他原因,你也许像自定义它们的实现,下面是几个例子。

  • 如果mapStateToProps需要花费昂贵的计算时间并且只关心你的状态的一小部分,那么你可以重写areStatesEqual。举个例子:areStatesEqual: (next, prev) => prev.entities.todos === next.entities.todos

  • 当你使用不纯的reducers时,你或许希望重写areStatesEqual,使它一直返回false。

  • You may wish to override areOwnPropsEqual as a way to whitelist incoming props. You'd also have to implement mapStateToProps, mapDispatchToProps and mergeProps to also whitelist props. (It may be simpler to achieve this other ways, for example by using recompose's mapProps.)

  • You may wish to override areStatePropsEqual to use strictEqual if your mapStateToProps uses a memoized selector that will only return a new object if a relevant prop has changed. This would be a very slight performance improvement, since would avoid extra equality checks on individual props each time mapStateToProps is called.

  • You may wish to override areMergedPropsEqual to implement a deepEqual if your selectors produce complex props. ex: nested objects, new arrays, etc. (The deep equal check should be faster than just re-rendering.)

返回值

根据配置信息,返回一个注入了 state 和 action creator 的 React高阶组件。这个组件是由connectAdvanced创建的。

例子

Inject just dispatch and don't listen to store
export default connect()(TodoApp)
Inject all action creators (addTodo, completeTodo, ...) without subscribing to the store
import * as actionCreators from './actionCreators'

export default connect(null, actionCreators)(TodoApp)
Inject dispatch and every field in the global state

Don’t do this! It kills any performance optimizations because TodoApp will rerender after every state change.
It’s better to have more granular connect() on several components in your view hierarchy that each only
listen to a relevant slice of the state.

export default connect(state => state)(TodoApp)
Inject dispatch and todos
function mapStateToProps(state) {
  return { todos: state.todos }
}

export default connect(mapStateToProps)(TodoApp)
Inject todos and all action creators
import * as actionCreators from './actionCreators'

function mapStateToProps(state) {
  return { todos: state.todos }
}

export default connect(mapStateToProps, actionCreators)(TodoApp)
Inject todos and all action creators (addTodo, completeTodo, ...) as actions
import * as actionCreators from './actionCreators'
import { bindActionCreators } from 'redux'

function mapStateToProps(state) {
  return { todos: state.todos }
}

function mapDispatchToProps(dispatch) {
  return { actions: bindActionCreators(actionCreators, dispatch) }
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
Inject todos and a specific action creator (addTodo)
import { addTodo } from './actionCreators'
import { bindActionCreators } from 'redux'

function mapStateToProps(state) {
  return { todos: state.todos }
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators({ addTodo }, dispatch)
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
Inject todos and specific action creators (addTodo and deleteTodo) with shorthand syntax
import { addTodo, deleteTodo } from './actionCreators'

function mapStateToProps(state) {
  return { todos: state.todos }
}

const mapDispatchToProps = {
  addTodo,
  deleteTodo
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
Inject todos, todoActionCreators as todoActions, and counterActionCreators as counterActions
import * as todoActionCreators from './todoActionCreators'
import * as counterActionCreators from './counterActionCreators'
import { bindActionCreators } from 'redux'

function mapStateToProps(state) {
  return { todos: state.todos }
}

function mapDispatchToProps(dispatch) {
  return {
    todoActions: bindActionCreators(todoActionCreators, dispatch),
    counterActions: bindActionCreators(counterActionCreators, dispatch)
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
Inject todos, and todoActionCreators and counterActionCreators together as actions
import * as todoActionCreators from './todoActionCreators'
import * as counterActionCreators from './counterActionCreators'
import { bindActionCreators } from 'redux'

function mapStateToProps(state) {
  return { todos: state.todos }
}

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(Object.assign({}, todoActionCreators, counterActionCreators), dispatch)
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
Inject todos, and all todoActionCreators and counterActionCreators directly as props
import * as todoActionCreators from './todoActionCreators'
import * as counterActionCreators from './counterActionCreators'
import { bindActionCreators } from 'redux'

function mapStateToProps(state) {
  return { todos: state.todos }
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators(Object.assign({}, todoActionCreators, counterActionCreators), dispatch)
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
Inject todos of a specific user depending on props
import * as actionCreators from './actionCreators'

function mapStateToProps(state, ownProps) {
  return { todos: state.todos[ownProps.userId] }
}

export default connect(mapStateToProps)(TodoApp)
Inject todos of a specific user depending on props, and inject props.userId into the action
import * as actionCreators from './actionCreators'

function mapStateToProps(state) {
  return { todos: state.todos }
}

function mergeProps(stateProps, dispatchProps, ownProps) {
  return Object.assign({}, ownProps, {
    todos: stateProps.todos[ownProps.userId],
    addTodo: (text) => dispatchProps.addTodo(ownProps.userId, text)
  })
}

export default connect(mapStateToProps, actionCreators, mergeProps)(TodoApp)
Factory functions

Factory functions can be used for performance optimizations

import { addTodo } from './actionCreators'

function mapStateToPropsFactory(initialState, initialProps) {
  const getSomeProperty= createSelector(...);
  const anotherProperty = 200 + initialState[initialProps.another];
  return function(state){
    return {
      anotherProperty,
      someProperty: getSomeProperty(state),
      todos: state.todos
    }
  }
}

function mapDispatchToPropsFactory(initialState, initialProps) {
  function goToSomeLink(){
    initialProps.history.push('some/link');
  }
  return function(dispatch){
    return {
      addTodo
    }
  }
}


export default connect(mapStateToPropsFactory, mapDispatchToPropsFactory)(TodoApp)

connectAdvanced(selectorFactory, [connectOptions])

将一个React组件连接到redux store上去。它是connect()的基础,但是对于如何将statepropsdispatch结合到最终的props上没有那么固定的限制。它不会对默认值或结果的记忆做任何假设,而是将这些责任留给调用者。

Arguments

  • selectorFactory(dispatch, factoryOptions): selector(state, ownProps): props (Function)

你可能感兴趣的:(react-redux文档翻译)