# 进阶

### React模块化约定 - DuckComponent

saga-duck将Redux层面进行了模块化，而React也可以进行同步的模块化，与duck一一对应。

我们约定传递 { duck, store, dispatch } 给组件props，它们分别是

* duck 对应的duck实例，可以访问它的 types、selectors、creators等及其它自定义属性
* store 对应完整的Redux store状态，**但是不允许直接访问它，而是应通过duck.selector/duck.selectors访问**
* dispatch 对应Redux store的dispatch方法

这里将遵循此约定的组件称为DuckComponent，它可以非常方便地与duck结合起来进行复用。

### Functional Stateless Component性能优化 <a href="#fsc" id="fsc"></a>

当前React还未对纯函数组件进行优化，每次都会触发重新渲染。我们可以利用 [purify](https://cyrilluce.gitbooks.io/saga-duck/content/utils.html) 来进行简单优化

```
import { purify } from 'saga-duck'
export default purify(function MyComponent(props){
    return <div />
})
```

purify会提供props**浅对比**，如果一致则跳过（通过shouldComponentUpdate方法），同时如果判断为DuckComponent（props中同时有duck与store属性），则不会直接对store对比，而是对比duck.selector(store)。

当然，purify也可以用于非函数的React组件

```
export default purify(class MyComponent extends React.Component{
    render(){
        return <div />
    }
})
// 如果是typescript，还可以这样用
// @purify
// class MyComponent extends ...
```

### 动态函数优化 <a href="#optimize-memorize" id="optimize-memorize"></a>

可能你经常会写这样的代码

```
function Container({duck, store, dispatch}){
    return <Foo handler={()=>dispatch(duck.creators.bar())} />
}
```

也许你已经知道这种情况下的Foo组件只进行浅对比是无效的，因为handler在每次render时都传递一个新的函数。

对于这种**只和duck与dispatch相关**的函数，我们可以通过[memorize](https://cyrilluce.gitbooks.io/saga-duck/content/utils.html)来使它变为固定的引用

```
import { memorize } from 'saga-duck'
const getHandler = memorize((duck, dispatch) => ()=>dispatch(duck.creators.bar()) )

function Container(props){
    const handler = gethandler(props)
    return <Foo handler={handler} />
}
```

当然对于传统React组件也是适用的

```
class Container extends Component{
    render(){
        const handler = gethandler(this)
        return <Foo handler={handler} />
    }
}
```

### saga业务逻辑健状性 <a href="#saga-ye-wu-luo-ji-jian-zhuang-xing" id="saga-ye-wu-luo-ji-jian-zhuang-xing"></a>

redux-saga通常只要出错没有try...catch，都会导致退出中止，建议使用`redux-saga-catch`库的相关方法进行包装，避免一处错误影响整个业务。

```
import { takeEvery, takeLatest } from 'redux-saga-catch'
```
