反应服务
您申请的内部 API .
一个反应服务是对问题的回答:
我申请时该怎么管理状态? Redux有很多锅炉板并拖慢了我们的脚步,MobX很棘手去调试并且有点魔法,组件状态+道具钻探很烦人并增加了不必要的复杂性,回放上下文很烦人要设置. 怎么办?
安装
npm install @adamdickinson/react-service
或者说
yarn add @adamdickinson/react-service
API 密码
只有一个方法你真的需要知道:
createService(hook) -> [ProviderComponent, UseServiceHook]
创建新服务的提供者和访问钩.
参数
钩子
用于曝光数据的反应钩函数.
回返
[提供组件,使用服务Hook]
就像反应一样 useState 方法,返回两个值 - 定义
提供方组件,以及服务钩的定义.
在您的应用程序中提供提供者组件, 向所有儿童提供获得确定服务的机会.
服务钩被设计在儿童部件内,以便 访问服务数据.
使用量
少说废话吧 时间到了 这里有几种方法 切实落实相同内容:
基本用途
我们想做一个随机数服务.
// 1. We define the service
const [RandomProvider, useRandom] = createService(({ max }: { max: number }) => {
const [number, setNumber] = useState<number>()
return {
update: () => setNumber(Math.floor(Math.random() * max)),
number,
}
})
// 2. We use the service with the `useRandom` hook in some components
const Displayer = () => {
const random = useRandom()
if (!random) return null
return <p>The number is {random.number}</p>
}
const Changer = () => {
const random = useRandom()
if (!random) return null
return <button onClick={random.update}>Randomize!</button>
}
// 3. We expose the service to those components that use it by rendering a parent `RandomProvider` component
ReactDOM.render(
<RandomProvider max={100}>
<Displayer />
<Changer />
</RandomProvider>,
document.getElementById('root')
)
用作代理服务
这就是我们如何定义服务。 我们首先简单扼要地界定数据 和过程...
// src/services/auth.ts
import createService from '@adamdickinson/react-service'
import store from 'store'
import { useEffect, useState } from 'react'
// Define our contract
interface User {
id: string
firstName: string
lastName: string
email: string
}
interface AuthAPI {
logIn(username: string, password: string): Promise<User>
logOut(): void
user?: User
}
// Define our API as a hook so we can leverage React functionality
const useAuthAPI = ({ serverUrl }: { serverUrl: string }) => {
const [user, setUser] = useState<User>()
const onChangeUser = (newUser?: User) => {
// Set local state, and persist change to storage
store.set('user', newUser)
setUser(newUser)
}
useEffect(() => {
// Restore existing user from persistent storage into local state
const existingUser = store.get('user')
if (existingUser) {
setUser(existingUser)
}
}, [])
const api: AuthAPI = {
logIn: async (username: string, password: string) => {
const response = await fetch(`${serverUrl}/login`)
if (!response.ok) {
throw new Error(response.statusText)
}
onChangeUser(await response.json())
},
logOut: () => onChangeUser(undefined),
user,
}
return api
}
const [AuthService, useAuth] = createService<AuthAPI>(useAuthAPI)
export { AuthService, useAuth }
...然后我们把它暴露在我们的应用程序... ...
// src/index.tsx
import ReactDOM from 'react-dom'
import App from './App'
import { AuthService } from './services/auth'
ReactDOM.render(
<AuthService serverUrl="http://api.myapp.com">
<App />
</AuthService>,
document.getElementById('root')
)
...最后,在我们需要的地方开始使用它!
// src/App.tsx
import { useAuth } from './services/auth'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
export default () => {
const auth = useAuth()
return (
<Router>
<Switch>
// Unauthed routes
{!auth?.user && <Route path="/" component={LogIn} />}
// Authed routes
{!!auth?.user && <Route path="/" component={Welcome} />}
</Switch>
</Router>
)
}
// src/containers/LogIn.tsx
import { useAuth } from './services/auth'
import { useState } from 'react'
export default () => {
const auth = useAuth()
const [loggingIn, setLoggingIn] = useState(false)
const [error, setError] = useState('')
const login = async () => {
setLoggingIn(true)
try {
await auth.logIn('me', 'my-pass')
} catch (error) {
setError(error?.message || error)
setLoggingIn(false)
}
}
return (
<>
{error && <p>{error}</p>}
<button onClick={login}>Log In</button>
</>
)
}
// src/containers/Welcome.tsx
import { useAuth } from './services/auth'
export default () => {
const auth = useAuth()
return `Welcome ${auth?.user?.firstName}!`
}
限制
任何好的图书馆都能找到它落下的地方 以及它想要的地方 改进。 为了让图书馆也成为好图书馆
太多服务破坏了汤
利用多种服务同时带来一些令人感兴趣的挑战:
1. 巢穴噩梦
看看这个(如果你敢的话):
const App = ({ children }) => (
<AuthProvider>
<APIProvider>
<CommentsProvider>
<PlaylistProvider>{children}</PlaylistProvider>
</CommentsProvider>
</APIProvider>
</AuthProvider>
)
它只使用四个随机命名的服务,但它已经成为一个巢穴 烂透了.
2. 服务间关系
假设我们有一个Auth服务 使用API服务进行通信 但API服务需要一个认证符号。 很快,我们发现 我们有一个循环依赖。 有一些办法可以应对,即: 将象征性联系的任务委托给打电话者而不是API 服务本身将它与一个呼叫联系起来,但这增加了更复杂.
3. 业绩风险
虽然我们广泛进行实验时没有出现业绩问题,但 这间图书馆,如果它们根本不存在,就有可能运行额外制作 需要更多的研究 要求在此确认或否认这一点.
没有太多的结构
Redux在其动作和还原器时设定了标准流程. 皆有明相而为相. 虽然这常常被视为一种诅咒,但它可以 也是一种祝福,因为它也定义了一个许多开发者可以工作的结构 与同时进行.
锅炉板很少,因此没有明显的结构 服务需求。 虽然这确实意味着 得到更多的工作 少了代码,它也使事物少了动词和结构.
还有吗?
开个玩笑!
有办法吗?
打开公关! 标准相当高,但反馈是任何 不错的拉动请求,所以期待 爱的任何贡献.