React + Redux 的一些建议(上篇)

Redux 并不是只和 React 结合使用的,它也可以和其他的很多类库结合起来一起使用,即使你还未开始深入使用,你也可以阅读文中的部分内容。

在深入 Redux 、Testing 或是其他更高级的使用之前,我们还是先开始 React 吧。

1、create-react-app:脚手架

我建议你可以首先采用 create-react-app 这个工具,他是Facebook For React 官方提供的零配置CLI 命令行工具。从技术上来说虽然它依然是一个脚手架,但是它屏蔽了所有的工具配置,你可以用它来快速生成一个React项目所需的基本工程。

sudo npm install create-react-app -g
create-react-app react-demo
cd react-demo && npm install
npm start

小结:
避免开始学习的时候就去使用脚手架
使用 create-react-app 去学习 react
当你熟悉 react之后
去探索工具本身如何使用
创建属于你自己的项目脚手架

2、JSX 语法

ReactDOM.render
使用 setState 来改变组件的状态 state
组件生命周期相关的方法
事件和表单
几种创建组件的方式
复合组件 composeable
高阶组件的使用和定义 HOC

3、什么时候引入 Redux

在你遇到应用的状态管理问题之前,你可以通过扩展应用的方式来解决,或是你在你的应用中压根就没遇到过这样的问题,因为你可以使用 setState 来很好的管理你的应用。但其实 setState 也不是那么高效,毕竟它也不是万能的。也许你会发现你已经在忙于处理太多的组件内部状态,那么,该是时候引入类似 Redux 等状态管理库了,不过有几个事情需要注意:

在学习 Redux 前得先学好 React
可以阅读以下You might not need Redux
不是所有的状态都需要放在 Redux 的 Store 中,也不能完全取代 setState

4、声明式的React组件

一般地,会有三种不同的方式来声明一个组件:

React.createClass 使用这个API来定义组件
React ES6 class components 使用 ES6 的class 来定义组件
Functional stateless components 通过函数直接定义无状态组件

// React.createClass
var TodoItem = React.createClass({ … })

// React ES6 class
class TodoItem extends React.Component { … }

// functional stateless component
function TodoItem() { … }

那什么时候该用什么方式来定义呢

无状态组件:适合用来声明没有组件生命周期方法并且没有内部状态的组件。这种写法很简单,就是一个纯函数,一个状态输入,输出就是elements。

5、示意的伪代码

(state) => View

这是一种最轻便最高效的组件声明方式,这种组件没有任何的内部状态,使用的时候也无法访问到组件的属性,所以一般建议能用这种方式声明组件的时候就尽量采用这种方式。

如果你需要使用组件生命周期方法,并且需要去处理组件内部状态(this.state) ,或者需要获取这个组件(this.ref)。那么,这个时候建议你使用ES6的 class 来声明组件。

另外,建议还是别用React.createClass这种方式声明组件了,Facebook 官方在React V0.13版本的时候就说过,以后的目标是使用ES6 classes的方式来定义,会完全废弃React.createClass

另外,这有两篇博文也推荐给你看:

should-i-use-react-createclass-es6-classes-or-stateless-functional-components(http://jamesknelson.com/should-i-use-react-createclass-es6-classes-or-stateless-functional-components/
react-create-class-versus-component(https://toddmotto.com/react-create-class-versus-component/

轻量级的函数式无状态组件

项目中一定需要去声明很多组件,我们可以一起来完成一个 TodoList 组件:

function TodoList({ list }) {
return (


{map(list, (item) =>
{item.name}
)}

);
}

我们还可以按函数的方式将其拆分

function TodoList({ list }) {
return (


{map(list, (item) => )}

);
}

function TodoItem({ item }) {
return

{item.name}
;
}

这个例子有些简单,无法很直接的看到这种定义方式的好处,但是当我们将组件拆分后将更具有可读性、可复用性以及可维护性。这种方式很灵活,而且很轻松就可以声明多个组件,一口气不费劲,推荐使用。

简洁的函数式无状态组件

我们可以使用 ES6 的 arrow functions 让组件的定义更加的清新。假如我们有一个这样的组件:

function Button({ onClick, children }) {
return (

{children}

);
}

我们可以将其用 ES6 的语法改写升级一下:

const Button = ({ onClick, children }) => {
return (

{children}

);
}

还可以再简单吗,我们来试一试:

const Button = ({ onClick, children }) =>

{children}

但这种方式就只允许我们的组件只有 props 作为输入,elements 作为输出。但如果我们希望在这中间做一些业务逻辑呢,我们可以将其再修改一下:

const Button = ({ onClick, children }) => {

// do something

return (

{children}

);
}

木偶组件Presenter Component和容器组件Container Component

好吧,这两个词听起来实在是别扭,听我慢慢道来。

React 中的组件其实也只是应用状态的一种表现方式,这让我们可以非常清晰的通过 (State) => View 这样的方式来理解。并且,组件内由处理程序来改变 state,从而改变不同 view 的展示。

那么,木偶组件和容器组件有什么区别或是怎么理解呢。

木偶组件只接受传递进来的 props 和 callback,然后返回对应需要展示的 view,这种组件比较单纯,大部分都是无状态组件,给我啥我就展示啥,给我什么callback我就执行callback,相同的输入总能得到相同的输出,像个机器人或是像个木偶,很纯粹很简单很可控;
而容器组件内更多的是关注逻辑,你需要在容器组件中准备好数据和一些callbac函数,在这里处理一些事件或管理内部的状态,给木偶组件传递所需的数据,大致的意思就是,容器组件对木偶组件说:调度或是逻辑处理的事就交给我吧,你需要啥我给你啥,你安心干你的活就行,保证给我的产出即可。

当项目中使用了Redux的时候,Container Component 有个更好理解的名字,就是Connected Component。这类组件和Redux的store进行了连接,并且获取到store的数据之后进行一些操作后传递给子组件。

Container components容器组件关注事情是怎么做的,Presenter components木偶组件关注怎么展现,各司其职,其乐融融。

另外,也再推荐给一篇文章smart-and-dumb-components,可以再更深入的理解。

什么时候该用 Container Components 容器组件呢

前面聊完,我想你应该知道两者的区别和使用场景了,但也许你还不太确定什么时候该用什么类型的组件。你可以定义一个Container Components,然后把一些Presenter Components都作为他的子组件,这样父组件关注如何工作,子组件关注如何展现。

但慢慢的,你发现父组件需要给子组件传递的properties和callbacks越来越多了,咋办呢,现在是时候来介绍两者如何结合使用了。

一般地,有个很好的原则:坚持presenter components不变,只新增一系列的container components去适应业务逻辑的改变。

把container component放到什么地方呢

父组件container component只关注state如何处理,现在你可以评估一下你的preenter component下面的子组件了。也许你会注意到preenter component下面的子组件没有被其他组件使用,那么找到这个组件的父组件,给它添加一个用于管理状态的container component,这样,父级的container component就能够变得更加清晰轻量,因为它没有必要去处理这些所有的状态。
很多presenters component也许只是包含一些只是为他们自己使用的props和callbacks,那么,也给他们加上一个container component去处理这些逻辑,把这些逻辑放到container component,这样将使父级的container component 再次变得轻量。

写出你的第一个高阶组件HOC吧

想象一下你需要展示一列内容,但是你不得不首先通过异步的方式获取这些内容项。现在你需要一个加载指示器来显示目前正在发送请求中,等请求完成后,你再展示获取到的内容项。

不过你可以更进一步来学习HOC了,一个高阶组件HOC将会返回一个增强的函数。

// 定义一个高阶组件

function withLoadingSpinner(Component) {
return function EnhancedComponent({ isLoading, …props }) {
if (!isLoading) {
return

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章