跳至主要內容

在本頁面上

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 - 將原子的值重置為其預設值。

交易範例

假設我們有兩個原子 positionStateheadingState,而且我們想要在單一動作中一起更新它們,其中 positionState 的新值是 positionStateheadingState 目前值的函數。

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()