test
2 months ago
useAbilities.js
2 weeks ago
useCompleteOnboarding.js
2 months ago
useDateRangePicker.js
3 months ago
useEmail.ts
3 months ago
useEngagementChartData.js
3 months ago
useLicenseSettings.js
3 months ago
useLink.js
3 months ago
useMcpAdapterInstall.js
2 weeks ago
useMediaDetail.js
3 months ago
useMediaLibrary.js
3 months ago
useMediaList.ts
3 months ago
usePerformanceSettings.js
3 months ago
useRegisterActivePage.js
3 months ago
useSettingOption.js
2 weeks ago
useSimpleSettingsPage.js
2 weeks ago
useTopPerforming.js
3 months ago
useTopVideosPaginated.js
3 months ago
useUpgradeCTA.js
3 months ago
useUserDetail.js
3 months ago
useSettingOption.js
73 lines
| 1 | import { useCallback, useMemo } from 'react'; |
| 2 | import isEqual from 'lodash/isEqual'; |
| 3 | import { useSettingsData } from '../pages/settings/shared/SettingsDataProvider'; |
| 4 | |
| 5 | const useSettingOption = ( optionKey, defaultValue ) => { |
| 6 | const { |
| 7 | settings, |
| 8 | lastSaved, |
| 9 | isLoading, |
| 10 | savingKeys, |
| 11 | updateLocal, |
| 12 | resetKey, |
| 13 | saveSlice, |
| 14 | } = useSettingsData(); |
| 15 | |
| 16 | // WP core's /wp/v2/settings returns `null` for any stored value that fails |
| 17 | // its registered schema (e.g. an empty string stored for a `boolean` option). |
| 18 | // Treat null the same as undefined so the UI falls back to the default and |
| 19 | // saves don't echo that null back — which WP rejects with |
| 20 | // `rest_invalid_stored_value`. |
| 21 | const rawData = settings?.[ optionKey ]; |
| 22 | const data = |
| 23 | rawData === undefined || rawData === null ? defaultValue : rawData; |
| 24 | |
| 25 | const savedValue = lastSaved?.[ optionKey ]; |
| 26 | const effectiveSaved = |
| 27 | savedValue === undefined || savedValue === null ? defaultValue : savedValue; |
| 28 | |
| 29 | const setData = useCallback( |
| 30 | ( next ) => updateLocal( optionKey, next ), |
| 31 | [ optionKey, updateLocal ] |
| 32 | ); |
| 33 | |
| 34 | const save = useCallback( |
| 35 | () => saveSlice( [ optionKey ] ), |
| 36 | [ saveSlice, optionKey ] |
| 37 | ); |
| 38 | const reset = useCallback( |
| 39 | () => resetKey( optionKey ), |
| 40 | [ resetKey, optionKey ] |
| 41 | ); |
| 42 | |
| 43 | // Derived (not a flag): typing + reverting is cleanly not-dirty, and pasting |
| 44 | // identical content doesn't falsely mark the page dirty. Deep equality is |
| 45 | // required because most option values are objects (e.g. branding, bunny_stream). |
| 46 | const isDirty = useMemo( |
| 47 | () => ! isEqual( data, effectiveSaved ), |
| 48 | [ data, effectiveSaved ] |
| 49 | ); |
| 50 | |
| 51 | const isSaving = savingKeys.has( optionKey ); |
| 52 | |
| 53 | // savedData is what the server actually has. Anything that hands the user a |
| 54 | // live endpoint or fires a request has to gate on this, not on `data` — |
| 55 | // otherwise flipping a switch advertises a connector the backend hasn't |
| 56 | // enabled yet. |
| 57 | return useMemo( |
| 58 | () => ( { |
| 59 | data, |
| 60 | savedData: effectiveSaved, |
| 61 | setData, |
| 62 | save, |
| 63 | reset, |
| 64 | isDirty, |
| 65 | isSaving, |
| 66 | isLoading, |
| 67 | } ), |
| 68 | [ data, effectiveSaved, setData, save, reset, isDirty, isSaving, isLoading ] |
| 69 | ); |
| 70 | }; |
| 71 | |
| 72 | export default useSettingOption; |
| 73 |