暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

前端实例 | React Recoil状态管理

605

在React Europe 2020 Conference上,Facebook内部开源了一种状态管理库Recoil。

Recoil是Facebook推出的一个全新的、实验性的JavaScript状态管理库,它解决了使用现

有Context API在构建较大应用时所面临的很多问题。


01

Recoil介绍

Recoil为了解决React全局数据流管理的问题,采用分散管理原子状态的设计模式。Recoil 提出了一个新的状态管理单位Atom,它是可更新和可订阅的,当一个Atom 被更新时,每个被订阅的组件都会用新的值来重新渲染。如果从多个组件中使用同一个Atom,则所有这些组件都会共享它们的状态。


02

Recoil核心概念

Recoil能创建一个数据流图(Data-Flow Graph),从 Atom(共享状态)到Selector(纯函数),再向下流向React组件。Atom 是组件可以订阅的状态单位。Selector 可以同步或异步转换此状态。

 1. RecoilRoot

对于使用Recoil的组件,需要将 RecoilRoot 放置在组件树上的任一父节点处。最好将其放在根组件中,如代码示例10-188所示。

代码示例 10-188

import React from 'react'
import ReactDOM from 'react-dom'
import { RecoilRoot } from 'recoil'
import App from './App'

ReactDOM.render(
<RecoilRoot>
<App />
</RecoilRoot>,
  document.getElementById('root')
)

2. Atom

Atom 是最小的状态单元。它们能够被订阅和更新: 当它更新时,所有订阅它的组件都会应用新数据重绘; 它能够在运行时创立; 它也能够在部分状态应用; 同一个Atom 能够被多个组件应用与共享。

相比Redux保护的全局Store,Recoil则采纳扩散治理原子状态的设计模式,不便进行代码分割。

Atom 和传统的state不同,它能够被任何组件订阅,当一个Atom 被更新时,每个被订阅的组件都会用新的值来重新渲染。

所以Atom 相当于一组state的汇合,扭转一个Atom 只会渲染特定的子组件,并不会让整个父组件重新渲染,代码如下:

import { atom } from 'recoil'
export const todoList = atom({
  key: 'todoList',
  default: [],
})


要创立一个Atom,必须提供一个key,其必须在RecoilRoot作用域中是唯一的,并且要提供一个默认值,默认值可以是一个动态值、函数甚至可以是一个异步函数。


03

Recoil核心API

Recoil采纳Hook形式订阅和更新状态,常用的API如下。

1. useRecoilState()

useRecoilState()函数是与useState()相似的一个Hook,能够对Atom 进行读写,如代码示例10-189所示。

代码示例 10-189   useRecoilState

import React, { useState } from 'react'
import { useRecoilState } from 'recoil'
import { TodoListStore } from './store'

export default function OperatePanel() {
  const [inputValue, setInputValue] = useState('')
  const [todoListData, setTodoListData] = useRecoilState(TodoListStore.todoList)

  const addItem = () => {
    const newList = [...todoListData, { thing: inputValue, isComplete: false }]
    setTodoListData(newList)
    setInputValue('')
  }

  return (
<div>
<h3>OperatePanel Page</h3>
<input type='text' value={inputValue} onChange={e => setInputValue(e.target.value)} >
<button onClick={addItem}>增加</button>
</div>
  )
}

2. useSetRecoilState()

useSetRecoilState()只获取setter()函数,不会返回state的值,如果只应用了这个函数,则状态变动不会导致组件重新渲染,如代码示例10-190所示。

代码示例 10-190  useSetRecoilState

import React from 'react'
import { useSetRecoilState } from 'recoil'
import { TodoListStore } from './store'
export default function SetPanel() {
  const setTodoListData = useSetRecoilState(TodoListStore.todoList)

  const clearData = () => {
    setTodoListData([])
  }

  return (
<div>
<button onClick={clearData}>清空recoil的数组</button>
</div>
  )
}

3. useRecoilValue()

useRecoilValue()函数只返回state的值,不提供修改办法,如代码示例10-191所示。

代码示例 10-191   useRecoilValue

import React from 'react'
import { useRecoilValue } from 'recoil'
import { TodoListStore } from './store'
export default function ShowPanel() {
  const todoListData = useRecoilValue(TodoListStore.todoList)
  return (
<div>
<h3>ShowPanel Page</h3>
      recoil中获取后果展现:
      {todoListData.map((item, index) => {
        return <div key={index}>{item.thing}</div>
      })}
</div>
  )
}

4. selector()

selector表示一段派生状态,它可以建设依赖于其Atom 的状态。它有一个强制性的get()函数,其作用与Redux的reselect或MobX的computed相似。

selector()是一个纯函数: 对于给定的一组输出,它们应始终产生相同的后果。这一点很重要,因为选择器可能会执行一次或多次,可能会重新启动或者被缓存,如代码示例10-192所示。

代码示例 10-192  selector

export const completeCountSelector = selector({
  key: 'completeCountSelector',
  get({ get }) {
    const completedList = get(todoList)
    return completedList.filter(item => item.isComplete).length
  },
})

selector()还可以返回一个异步函数,能够将一个Promise作为返回值。


精彩预告

前端实例:设计一个企业级脚手架工具

前端实例:用Vue 3.0设计一套组件库


02

参考书籍

《大前端三剑客——Vue+React+Flutter》

ISBN:978-7-302-61474-6

徐礼文 

定价:209.00元


内容简介

本书通过介绍三大前端框架及生态体系,带领读者全面掌握从移动互联应用开发到万物互联应用开发技术和实战技巧,本书也可以作为前端开发者搭建企业级前端产品体系的参考书。书中提供了大量的代码示例,读者可以通过这些例子理解知识点,也可以直接在开发实战中稍加修改应用这些代码。另外,提供书中所有案例所涉及的源代码,以便于读者高效的学习。


扫码京东优惠购书


相关图书推荐





文章转载自清华计算机学堂,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论