原文地址: Stop Asking if React Hooks Replace Redux
许多同事一直问我一些相似的问题:html
“若是咱们在项目中使用hooks,咱们是否还须要Redux?”react
“React Hooks会不会使Redux太过期了?我能不能用Hooks来作全部Redux能作的事呢?”git
在Google中搜索会发现,你们常常问这些问题。github
“React Hooks是否会取代Redux?”,最简单的回答是“不必定”。redux
更细致但礼貌的答案是“嗯,那取决于你正在作的项目类型”。api
我更倾向于告诉你们的答案是“我不肯定你是否知道你在说什么”。有几个缘由能够说明,为何“React Hooks是否会取代Redux”是一个本质上有缺陷的问题。首先:数组
经过Dan Abramov(Redux的创造者之一)的一篇文章【You Might Not Need Redux】能够看出,若是你不须要使用它,则无需替换任何东西。app
Redux是一个JavaScript库,而且若是你用的是React(另外一个JavaScript库),那么为了使用Redux,你还须要在应用中加载一个React-Redux的JavaScript库。在项目中使用依赖库会增长打包体积,这会增长你应用的加载时间。基于这个缘由,你不该该使用一些库,像jQuery、Redux、MobX(另外一个状态管理库),甚至是React,除非你有明确的理由要使用它们。ide
当你们问到“是否hooks会替代Redux”,他们彷佛常常以为,他们的React应用须要使用其中一种。事实并不是如此,若是你正在写的应用没有不少状态须要被储存,或者你的组件结构很简单,能够避免过分的prop传递,以及基于React自己提供的特性,你的状态已经足够可控了,无论有没有hooks,这些状况使用状态管理就没有多大意义了。函数
即便你确实有许多的状态,或者有像老树根同样扭曲分叉的React组件结构,你仍然不须要状态管理库。Prop传递可能很麻烦,可是React给了你许多状态管理选项,而且hooks绝对能够帮你很好地组织状态。Redux是一个轻量级的库,可是它的设置很复杂,增长了打包体积,而且不少地方须要权衡。有不少缘由能够说明,为何你应该选择不在项目中使用它,而且这些缘由颇有说服力。
你并不老是须要Redux,这也是在说,你依然有许多理由去使用它的。若是你的项目在一开始就使用了Redux,那么它多是一个很好的理由,不管它是否作了这些:组织(应用状态的可预测性、单一的数据流,在复杂的应用中颇有用)、中间件、Redux的强有力的开发工具和调试能力。若是你有使用Redux的理由,它不会由于React Hooks变得无效。若是你以前须要Redux,那么你如今仍然须要。这是由于:
Redux是一个状态管理库,Hooks是React最近更新的部分特性,让你的函数组件能够作类组件能作的事情。
因此不使用类组件来写React应用忽然会让状态管理库变得过期了呢?
固然不会!
经过文档能够看出,React Hooks被开发出来主要是这三个理由:
注意,没有一条理由的动机直接代表要作一些与状态管理相关的事情。
话说如此,React Hooks确实提供了一些选择去管理应用的状态。尤为是useState
、useReducer
和useContext
方法,提供来新的方式去维护你的状态,这被证实比先前React提供的选项更好、更有条理。
可是这些hooks并非什么新东西或神奇的东西,而且它们也没有使状态管理过期,由于事实是:
那就对了,你如今能够写函数组件来作一些之前只能用类组件来作的事情,可是这些函数组件并不能作一些类组件作不到的事情,除了能够更好地组织和复用代码的能力。它们不必定让你的应用更好,而是让开发者的体验更好。
useState
和useReducer
只是管理组件状态的方法,而且它们的工做原理同类组件的this.state
和this.setState
是同样的,你仍然须要传递你的props。
useContext
是你们认为在Redux板上钉钉的特性,由于它可让你在组件之间共享应用的状态,而不须要经过prop传递,可是它也没有真正的作任何新的事情。context API如今是React的一部分,useContext
仅仅是让你不用<Consumer>
包裹也可使用context。而且有一些开发这用context来管理整个应用的状态,这不是设计context的目的。经过文档能够看出:
Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language.Context是为了共享数据而被设计出来的,能够认为是React组件树的“全局”,好比当前已受权的用户、主题或者首选的语言。
换句话说,就是那些预计不会频繁更新的东西。
文档中也建议有节制地使用context,由于“它会使得组件难以复用”。他们也提醒开发者,若是开发者不当心,context很容易触发没必要要的重复渲染。
我见过项目成功地使用React Context来管理应用状态,这是有可能的,也不失为一种选择。可是状态管理并不彻底是context被设计出来去作的事情,并且Redux和其余状态管理库被设计出来就是为了处理这种特定的目的。
此外,React Hooks也毫不意味着Redux的消亡,由于若是你看一眼React-Redux最近更新的文档,你会明白:
没错,React Hooks正在帮助React-Redux恢复活力并移除来它的一些痛点,与“替代”的说法相差甚远。
我在另外一篇文章中对React-Redux进行了深刻研究,这里要说的重点。在hooks以前,你必须定义mapStateToProps
和mapDispatchToProps
两个函数,而且用connect
包裹你的组件来建立一个高阶组件,它会传递dispatch方法和部分Redux贮存的状态,这些状态是你在mapping函数中指定做为props传递到组件中的。
让咱们来看一个很是简单的计数器应用的例子(太简单甚至都不须要Redux,可是这里主要是为了展现一些信息)。假设咱们已经定义了Redux store和increment
、decrement
两个action creator(完整的源码在这里)。
import React from 'react'; import {connect} from 'react-redux'; import * as actions from '../actions/actions'; class App extends React.Component { constructor(props) { super(props); } render() { const {count, increment, decrement} = this.props; return ( <div> <h1>The count is {count}</h1> <button onClick={() => increment(count)}>+</button> <button onClick={() => decrement(count)}>-</button> </div> ); } } const mapStateToProps = store => ({ count: store.count }); const mapDispatchToProps = dispatch => ({ increment: count => dispatch(actions.increment(count)), decrement: count => dispatch(actions.decrement(count)) }); export default connect(mapStateToProps, mapDispatchToProps)(App);
太使人烦恼了!若是咱们没必要包裹组件到高阶组件中,就可让组件取到Redux store的值,这样不是更友好吗?是的,这就是hooks出现的缘由。Hooks就是为了复用代码和消除因为高阶组件产生的“嵌套地狱”。下面是一个相同的组件,使用React-Redux hooks转换成函数组件。
import React from 'react'; import * as actions from '../actions/actions'; import {useSelector, useDispatch} from 'react-redux'; const App = () => { const dispatch = useDispatch(); const count = useSelector(store => store.count); return ( <div> <h1>The count is {count}</h1> <button onClick={() => dispatch(actions.increment(count))}>+</button> <button onClick={() => dispatch(actions.decrement(count))}>-</button> </div> ); } export default App;
是否是很漂亮?简而言之,useSelector
让你能够保存部分Redux store的值到你的组件。useDispatch
更简单,它仅仅为你提供了一个dispatch函数,你能够用它来发送状态更新到Redux store。最棒的是,你再也不须要写这些丑陋的mapping函数和用connect
函数来包裹组件。如今,一切都很好地包含在你的组件中,它更简洁,所以更容易阅读,而且更有条理。重点是:
毫无疑问,这两项技术能够很好地互补。React Hooks不会替代Redux,它们仅仅为你提供来新的、更好的方式去组织你的React应用。若是你最终决定使用Redux来管理状态,可让你编写更好的链接组件。
因此,请不要再问“React Hooks是否会取代Redux?”。
相反,开始问本身“我正在制做什么样的应用?我须要什么样的状态管理?Redux能够用吗,仍是有些过分使用呢?hooks能够用吗,仍是应该用类组件?若是我决定使用Redux和React Hooks(或者MobX和React Hooks,或者Redux和jQuery,不用React——这些都是有效的选择,取决于你正在作的事情),那么我怎样可使这些技术互补而且和谐共处呢?”。