React JS: 如何使用 RxService 管理狀態
阿新 • • 發佈:2021-07-29
快速使用 vite 建立一個react-ts專案
λ npm init vite@latest
npx: 6 安裝成功,用時 2.033 秒
√ Project name: ... myapp
√ Select a framework: » react
√ Select a variant: » react-ts
λ cd myapp
λ npm install
下載 rxjs 和 react-rxbuilder
λ npm i rxjs react-rxbuilder
使用編輯器向 tsconfig.json 新增兩項,用於支援裝飾器語法和Metadata元資料
{ "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true, }, }
在根元件掛載 RxService 元件
import { RxService } from "react-rxbuilder";
ReactDOM.render(
<React.StrictMode>
<RxService>{() => <App />}</RxService>
</React.StrictMode>,
document.getElementById("root")
);
通常你只需要在你的程式中使用一次 RxService
在 App 元件中建立 Service
import { Injectable } from "react-rxbuilder"; @Injectable() class CountService { i = 0; inc() { this.i++; } }
使用 Injectable 將一個類快速註冊為 Service
在元件中使用 CountService
function App() {
const [countService] = useService(CountService);
return (
<div className="App">
<h2>{countService.i}</h2>
<button onClick={countService.inc}>Inc</button>
</div>
);
}
現在你的 App.tsx
import React from "react";
import { Injectable, useService } from "react-rxbuilder";
@Injectable()
class CountService {
i = 0;
inc() {
this.i++;
}
}
function App() {
const [countService] = useService(CountService);
return (
<div className="App">
<h2>{countService.i}</h2>
<button onClick={countService.inc}>Inc</button>
</div>
);
}
export default App;
啟動開發伺服器,然後在頁面中點選 button 看看
λ npm run dev
現在我想在點選按鈕時,列印一些log資訊,如何在元件中使用多個 Service ?
繼續使用 Injectable 建立 LogService
@Injectable()
class LogService {
log() {
console.log(new Date().toLocaleString());
}
}
然後在 App 元件中使用
function App() {
const [countService, logService] = useService(CountService, LogService);
return (
<div className="App">
<h2>{countService.i}</h2>
<button onClick={() => (countService.inc(), logService.log())}>
Inc
</button>
</div>
);
}
現在點選按鈕的同時,在控制檯記錄訊息
為了簡化程式碼,我們可以在 CountService 中使用 LogService
@Injectable()
class CountService {
constructor(public readonly logService: LogService) {}
i = 0;
inc() {
this.i++;
this.logService.log();
}
}
上面使用了 constructor 依賴注入,但是你開啟伺服器可能會遇到 this.logService 是 undefined 的情況,應為vite使用的是esbuild,可以使用 swc代替 esbuild
還有一種解決方案是使用靜態屬性代替 constructor 依賴注入
最後的程式碼如下
import React from "react";
import { Injectable, useService } from "react-rxbuilder";
import "reflect-metadata";
@Injectable()
class LogService {
static ins: LogService;
log() {
console.log(new Date().toLocaleString());
}
}
@Injectable()
class CountService {
readonly logService = LogService.ins;
i = 0;
inc() {
this.i++;
this.logService.log();
}
}
function App() {
const [countService] = useService(CountService);
return (
<div className="App">
<h2>{countService.i}</h2>
<button onClick={countService.inc}>Inc</button>
</div>
);
}
export default App;