该不该用context api来支持redux?

更新日期: 2021-06-13阅读: 783标签: React

react 16.3的API,戏称“redux末末的官方分享数据api,到底是什么药?又是真正的正方能在社群里重新扮演被追随的redux套装(马克)” Ericson表示没这自己!)几天来发表一下个人实际玩的看法,顺便提供我认为如何使用context api的


redux 与 context api 解决开发问题?


“Props down Event up”单向数据流React写到一个程度,一定要会一个重要的概念:单向资料流,React App要按照行资料从上到下的方向性,如果子元件的状态改变了会影响到整个父元件或共享元件,那么通过事件回调或调度动作去通知父组件的更改,父组件再通过道具传递传递给子组件更新画面更新。

当你的状态变化会导致复数元件需要同时更新画面的时候,就应该上浮到父状态暂存,只要父子之间只有两层级这样状态与回调通过props交还算好的处理,不过试想中间有许多五六层元件的包装器,如果它们的道具需要二级维护,结果就是传播,你的预知是在传播,而不是在写程序还是很容易造成的错误。

要解决这种被戏称为道具钻探的问题,“通过一个集中式的数据存储,需要/更新/更新共同状态的组件可以相互共享HOC数据存储,一来我们还是保持资料流的来向性,但同时还能隔空抓药,不必透过层层获取状态。

应用架构被称为fluxor、reflux、redux……但在FB只与当年“react打家同时推出”,但并没有官方给出的概念,一百倍时间争夺:fluxxor、reflux、redux……但最后redux杀出一条血路最终套件变成了社区间最崇尚的流感实作。


redux都一统江湖了那用什么context api?

我不认为其团队出的文字只是掉出剑刺的上下文,干掉充,冒着补漏的痕迹,让漏水的情况下自己反应过来的情况下,可以说是不痛不痒的。 '已经有基础的state/setState可以做跟生命周期管理连接得很好了,何必从状态组件很好呢?

redux 却没有自己的问题,虽然可以通过combineReducers把reducers分拆成多个文件再集成,但可以完成因为关注点的分离,整个应用仍然是共享的Data Store,取state/action名的时候都要另外注意时会委托状态如果也存在某个父节点,那么如果实际没有到全域,则有一个碰撞设置了(UI上的状态)另外的学习窗帘,环境,很很难马上上手。

Context api可以说,只是可以说是在某个地方没有简单的处理数据,或者说它是一个简单的地方道具钻的问题,那么context api不失为一个简单的解法。


正确的使用姿势

下面我会用一个简单的 Counterstrategy 来解释如何使用上下文

首先新开一个文件context.js,我们用React.createContext实体化一个context物件,这个物件有两个Component:Provider、Consumer

import React from 'react'
const ctx = React.createContext()
export const {Provider, Consumer} = ctx
export const withCounter = Component => props => <Consumer>{value => <Component {...props} counter={value} />}</Consumer>
export default ctx

我最漂亮的做法是写一个HOC,类比类似发现redux的connect,又是react-routers的withRouter。通过 props.counter 抽取计数器对象的状态/方法

使用HOC的好处是任何需要接上这个上下文的元件,只要用Counter接上进口,好后出口就可以包好很多复制上的重复动作……

我们在HOC里看到context的Consumer包住了一个元件,这个Consumer Code签名如下:

<Consumer> 
{value => <Component counter={value} />}
</Consumer>

你可以把你当成类似redux里的道具,可以把国家的地图作为道具包装的关键所在,所以顾虑部分可以命名,因为用计数器来命名,因为用计数器作为关键,至价值从何而来长别的?急,底下为你划分

开一个新档Counter.js,我们把这个我们当成Counter最顶的父元件,所有Counter相关的状态/方法都会存在这个父元件的状态中

import React from 'react'
import { Provider } from './context'

class Counter extends React.Component {

constructor (props) {
super(props)
this.state = {
counter: {
value: 0,
inc: this.inc,
dec: this.dec
}
}
}

inc = () => {
this.setState(({counter})=>({
counter: {
...counter,
value: counter.value+1
}
}))
}

dec = () => {
this.setState(({counter})=>({
counter: {
...counter,
value: counter.value-1
}
}))
}

render () {
return (
<Provider value={this.state.counter}>
<CounterCard/>
</Provider>
)
}

}

export default Counter

在上面的例子中,我存了一个计数器对象在状态中,包含了一个计数对象在状态中的数字值还有一个递增(inc)与递减(dec)的方法

this.state = { 
counter: {
value: 0,
inc: this.inc,
dec: this.dec
}
}

不外用这递增递减的部分就是用setState去state.counter.value更新至render function我们会发现context Provider实际用在

render () { 
return (
<Provider value={this.state.counter}>
<CounterCard/>
</Provider>
)
}

如果你觉得应该会,“有点小小的消费就是从敏锐发现的价值应该不会是提供者来的”

答对了!仿佛是用洞当接上一样,虫底价的时候,所有供应商跟供应商下同价值条款的时候,跟所有供应商联系更新后的内容。

你读过redux原码,码作法其实大同小异(毕竟redux原作者丹神都去react组了XD)不过与redux不同的点在context api并没有dispatch这样的概念,所以我得将方法通过value一并传递给消费者,这样的子组件能够调用递增/递减更新状态。

负责我们来处理细部元件,首先是按钮,我们需要一个+按钮跟一个-按钮

import React from 'react'
import { withCounter } from './context'

const IncBtn = ({ counter }) => <button type='button' className='btn btn-primary btn-block' onClick={counter.inc}>+</button>
const CounterIncBtn = withCounter(IncBtn)

export default CounterIncBtn

这时候我们先创建一个无状态组件叫IncBtn,从props里面这个counter之后,将住按钮点击绑定上counter.inc方法,然后从context.js里面import with CounterHOC来包IncBtn,这样IncBtn就会接收到counter这个道具

递减按钮也是同样的步骤,在点击修改counter.dec,接下来看看下个元件

import React from 'react'
import { withCounter } from './context'

const Display = ({ counter }) => <h5 className="card-title text-center">{counter.value}</h5>
const CounterDisplay = withCounter(Display)

export default CounterDisplay

我们再次创建一个无状态组件Display,用Counter包着确定他会接收到这个props,然后在h5里面把counter.value指定给印出来

一个计数卡可以很容易地定义布局,把上面的按钮与显示元件一个萝卜一个坑的放好

import React from 'react'
import CounterDisplay from './CounterDisplay'
import CounterIncBtn from './CounterIncBtn'
import CounterDecBtn from './CounterDecBtn'

const CounterCard = () => (
<div className='Counter card m-3'>
<div className='card-body'>
<CounterDisplay/>
<div className='row'>
<div className='col'><CounterDecBtn /></div>
<div className='col'><CounterIncBtn /></div>
</div>
</div>
</div>
)

export default CounterCard

整个阶层从CounterCard -> CounterDisplay & CounterButton> 是两层但我们并没有用大老算下来的道具 - 一路跟callback方法一起传下去,因为他们都已经通过与Counter HOC接好。

必须是用jsFiddle写出的例子,因为将所有的组件放在一起所以许读者,不过聪明下的看我在活生生的故事。

看到这有一个API只是一个看似简单的版本没有redux?


结语

所以,我应该把整体改用语境吗?

不,当然不!如果你的Production redux用得的,浪费去改改,千万别有时间自营新环境,语境就是一个替代方案,顶多在写组件不想要reduction的时候,可以尝试用上下文来解。

但如果你是开新的做,那么问题就变成专案……

我需要继续使用redux吗?

这个问题就比较式开放,这个问题,我公司新开的专案架构,以数据获取部分导入relay/graphql,对于redux在专案内的模式降低,不同的状态在配着redux-persist(local) persistence)或reselect(计算状态缓存)使用,若计去画将redux完全拿掉,完全靠context api跟自己写的lib/helper应该过得。

另外根据丹神react 17的抢先看,异步渲染模式看不出非得仰赖redux来处理数据获取副作用的需求,所以如果是我当家说的话,我可能会把redux从新专案架构中移除。

你可能不需要 Redux

是redux的维护者经常挂边解说的一句话,老话一句,多种情况下有多种不同的考量,选择工具一向没有什么正解,不能贴合团队的需求最重要!希望这篇文章能让你对上下文有能力的,帮助你做出适当的选择。

来自:https://medium.com/@nightspirit622/該不該用context-api-來取代-redux-4d7395d5c8da


链接: https://fly63.com/article/detial/11734

如何优雅的设计 React 组件

如今的 Web 前端已被 React、Vue 和 Angular 三分天下,尽管现在的 jQuery 已不再那么流行,但 jQuery 的设计思想还是非常值得致敬和学习的,特别是 jQuery 的插件化。

React深度编程:受控组件与非受控组件

受控组件与非受控组件在官网与国内网上的资料都不多,有些人觉得它可有可不有,也不在意。这恰恰显示React的威力,满足不同规模大小的工程需求。

React框架学习_关于React两种构建应用方式选择

一般在传统模式下,我们构建前端项目很简单。就是下载各种js文件,如JQuery、Echart等,直接放置在html静态文件。Webpack则是JavaScript中比较知名的打包工具。这两个构建工具构成了React应用快速搭建的基础。

Gatsby.js_一款基于React.js静态站点生成工具

Gatsby能快速的使用 React 生态系统来生成静态网站,可以结合React Component、Markdown 和服务端渲染来完成静态网站生成让他更强大。

React创建组件的三种方式及其区别

React推出后,出于不同的原因先后出现三种定义react组件的方式,殊途同归;具体的三种方式:函数式定义的无状态组件、es5原生方式React.createClass定义的组件、es6形式的extends React.Component定义的组件

react生命周期详解_深入理解React生命周期

React主要思想是通过构建可复用组件来构建用户界面,每个组件都有自己的生命周期,它规定了组件的状态和方法需要在哪个阶段改变和执行。所谓组件就是有限状态机,,表示有限个状态以及在这些状态之间的转移和动作行为的模型。

React + Webpack 构建打包优化

React 相关的优化:使用 babel-react-optimize 对 React 代码进行优化,检查没有使用的库,去除 import 引用,按需打包所用的类库,比如 lodash 、echarts 等.Webpack 构建打包存在的问题两个方面:构建速度慢,打包后的文件体积过大

react router中页面传值的三种方法

这篇文章主要介绍React Router定义路由之后如何传值,有关React和React Router 。react router中页面传值的三种方法:props.params、query、state

react 高阶组件的 理解和应用

react 高阶组件简单的理解是:一个包装了另一个基础组件的组件。高阶组件的两种形式:属性代理(Props Proxy)、反向继承 (Inheritance Inversion)

react中的refs属性的使用方法

React 支持一种非常特殊的属性 Ref ,你可以用来绑定到 render() 输出的任何组件上。这个特殊的属性允许你引用 render() 返回的相应的支撑实例( backing instance )。这样就可以确保在任何时间总是拿到正确的实例

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!