#### 1.Redux导致的组件多余的渲染问题
请仔细阅读[React 组件间通讯](http://taobaofed.org/blog/2016/11/17/react-components-communication/)的文章的最后一个例子,最后的输出结果为:

这是因为在最后一个定时器中是如下的代码:
```js
setTimeout(() => {
store.dispatch({
type: 'child_2_1',
data: 'bye'
})
}, 2000);
```
此时你必须了解redux的观察者模式,当你dispatch一个事件的时候,我们的Child_2与Child_2_1中subscribe的事件都会被执行,所以首先是Child_2_1直接进行了一次更新,然后接着由于Child_2的更新有发生了一次更新,所以Child_2_1总共在后面的dispatch中输出了两次,即渲染了两次。对于redux的观察者模式不了解的可以[查看redux原理分析](https://github.com/liangklfangl/redux-createstore)。同时,该文章给出了react兄弟组件通信的方法:即采用观察者模式或者redux(实际上也是观察者模式)来解决
#### 2.React开发中那些设计模式
(1)使用this.props.children来处理组件的低耦合。此时,父组件可以访问和读取子组件。而我们以前直接将Navigator组件写入到Header组件的方式一方面使得测试不容易(当然,在测试中可以使用[shallow-rendering](https://facebook.github.io/react/docs/test-utils.html#shallow-rendering)的方式来解决),另一方面我们的Header和Navigator将会强耦合,对于一些不需要Navigator的Header组件来说就无法实现复用
(2)高阶组件可以很容易的实现逻辑的复用,对于一些重复的逻辑可以考虑使用[高阶组件](https://github.com/liangklfangl/high-order-reducer)来完成。下面的例子就为我们的初始组件添加了一个title属性:
```js
var config = require('path/to/configuration');
var enhanceComponent = (Component) =>
class Enhance extends React.Component {
render() {
return (
Hello world.<\/p>; class App extends React.Component { render() { return React.createElement(enhanceComponent(OriginalComponent)); } }; ``` 这段代码速度比较慢,每次都会清除OriginalComponent组件和其子组件的DOM和state状态,即完全重新渲染,因为enhanceComponent(OriginalComponent)每次都会给你返回一个不同的class,而根据React的component diff算法,组件本身的类型发生了改变,因此需要reRender。只要简单的修改如下: ```js var OriginalComponent = () =>
Hello world.<\/p>; var EnhancedComponent = enhanceComponent(OriginalComponent); class App extends React.Component { render() { return React.createElement(EnhancedComponent); } }; ``` 此时render方法每次返回的都是同类型的EnhancedComponent。你可以查看[React的component diff](https://zhuanlan.zhihu.com/p/20346379?columnSlug=purerender) (3)我们写的大部分的模块和组件都会存在依赖关系,特别是当树形的组件树存在的时候,父子关系的依赖就会出现了。因此,项目成功的一个关键就是如何去管理这些依赖关系。此时你应该要考虑到一个广为人知的设计模式,也就是 我们所说的:依赖注入。我们给出下面的例子: ```js // Title.jsx export default function Title(props) { return
(1)当模块首次被加载的时候会被缓存,也就是说每次调用require('foo')都会得到完全相同的对象,只要这个模块对应于同一个文件。
(2)多次调用require('foo');不会导致模块代码被多次执行,这是一个很重要的特性。利用这个特性,我们将会返回一个"部分完整"的对象(引用),从而允许那些过渡的依赖被加载,即使这些过渡的依赖存在循环引用的关系。
那么上面说的这些为什么能够处理我们的依赖注入呢?其实,每次我们导出一个对象的时候我们导出的其实是一个`单例对象`,其他的模块使用这个模块的时候,引入的对象也是同一个对象。这样的话,我们可以先注册我们的依赖,然后在其他文件中直接引入这个依赖。如下面的例子:
```js
var dependencies = {};
export function register(key, dependency) {
dependencies[key] = dependency;
}
//fetch方法从全局变量dependencies获取数据
export function fetch(key) {
if (dependencies[key]) return dependencies[key];
throw new Error(`"${ key } is not registered as dependency.`);
}
export function wire(Component, deps, mapper) {
return class Injector extends React.Component {
constructor(props) {
super(props);
this._resolvedDependencies = mapper(...deps.map(fetch));
}
render() {
return (