在本頁面上
useRecoilTransaction_UNSTABLE(callback, deps)
建立一個交易回呼,可以用來以安全、簡單、有效率的方式原子化地更新多個原子。提供一個交易回呼,作為一個純函式,它可以get()
或set()
多個原子。交易類似於設定 Recoil 狀態的「更新器」表單,但可以涵蓋多個原子。寫入項目對於同一個交易內後續的讀取項目來說是可見的。
- 除了交易之外,此鉤子也有用於
- 實作簡化器樣式,以對多個原子執行動作。
- 動態更新一個原子,在渲染時我們可能不確定我們想要更新哪個原子或選擇器,因此無法使用
useSetRecoilState()
。
interface TransactionInterface {
get: <T>(RecoilValue<T>) => T;
set: <T>(RecoilState<T>, (T => T) | T) => void;
reset: <T>(RecoilState<T>) => void;
}
function useRecoilTransaction_UNSTABLE<Args>(
callback: TransactionInterface => (...Args) => void,
deps?: $ReadOnlyArray<mixed>,
): (...Args) => void
- 複製
deps
- 暫存回呼函式的選用相依關係集。如同useCallback()
,所產生的事務回呼函式預設不會暫存,而且會在每次渲染中產生一個新函式。你可以傳入一個空的陣列,以始終傳回同一個函式實例。如果你在deps
陣列中傳入值,在任何依賴項的參考相等性改變時,將會使用一個新的函式。然後可以在回呼函式的內文中使用這些值,而不會過時。(請參閱useCallback
)你可以 更新 eslint,以協助確保正確認用這個函式。
交易介面
get
- 取得要求的 Recoil 狀態的目前值,反映更早之前在交易中執行的任何寫入。目前這僅支援同步原子。set
- 設定原子的值。你可以直接提供新值,也可以提供更新函式,其中傳回新值並將目前值作為參數。目前值表示目前交易中所有其他已決狀態變更。reset
- 將原子的值重置為其預設值。
交易範例
假設我們有兩個原子 positionState
和 headingState
,而且我們想要在單一動作中一起更新它們,其中 positionState
的新值是 positionState
和 headingState
目前值的函數。
const goForward = useRecoilTransaction_UNSTABLE(({get, set}) => (distance) => {
const heading = get(headingState);
const position = get(positionState);
set(positionState, {
x: position.x + cos(heading) * distance,
y: position.y + sin(heading) * distance,
});
});
然後你可以只要在事件處理常式中呼叫 goForward(distance)
,即可執行交易。這會根據目前值更新狀態,而不是在元件渲染時的狀態。
你也可以在交易中讀取之前寫入的值。因為在更新常式執行的時候不會提交任何其他更新,所以你會看到狀態的一致性儲存。
const moveInAnL = useRecoilTransaction_UNSTABLE(({get, set}) => () => {
// Move Forward 1
const heading = get(headingState);
const position = get(positionState);
set(positionState, {
x: position.x + cos(heading),
y: position.y + sin(heading),
});
// Turn Right
set(headingState, heading => heading + 90);
// Move Forward 1
const newHeading = get(headingState);
const newPosition = get(positionState);
set(positionState, {
x: newPosition.x + cos(newHeading),
y: newPosition.y + sin(newHeading),
});
});
還原範例
這個勾子對於執行多個原子上的動作,來實作還原模式,也很有用。
const reducer = useRecoilTransaction_UNSTABLE(({get, set}) => action => {
switch(action.type) {
case 'goForward':
const heading = get(headingState);
set(positionState, position => {
x: position.x + cos(heading) * action.distance,
y: position.y + sin(heading) * action.distance,
});
break;
case 'turn':
set(headingState, action.heading);
break;
}
});
目前限制和未來願景
- 交易目前僅支援原子,尚不支援選擇器。可以在未來加入這項支援。
- 預設值為選擇器的原子目前也不受支援。
- 已讀取的原子必須有同步值。如果它在錯誤狀態或非同步處理狀態,則交易會擲回錯誤。若依賴項處理中,可以透過中止交易並在可用的時候重新啟動交易,來支援處理中依賴項。這與選擇器
get()
的實作方式一致。 - 交易沒有回傳值。如果我們想要擁有交易完成的一些通知,或使用交易要求慢速數據,或要求事件處理常式的資料,那麼可以有交易回傳一個
Promise
到回傳值。 - 交易必須是同步的。有一個允許非同步交易的提案。使用者可以提供一個
async
交易回呼函式,它可以使用await
。然而,在交易回傳的Promise
完全解析之前,所有設定的原子更新都不會套用。 - 交易不得有任何副作用。如果您需要副作用,請改用
useRecoilCallback()
。