react-redux文档翻译

英文文档链接

API


<Provider store>

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

Props

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

Example

Vanilla React
ReactDOM.render(
  <Provider store={store}>
    <MyRootComponent />
  </Provider>,
  rootEl
)
React Router
ReactDOM.render(
  <Provider store={store}>
    <Router history={history}>
      <Route path="/" component={App}>
        <Route path="foo" component={Foo}/>
        <Route path="bar" component={Bar}/>
      </Route>
    </Router>
  </Provider>,
  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)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容