feat: useBoolean hook (#2314)
* feat: Add useBoolean hook and example usage * More example usage * chore: More useBoolean conversion
This commit is contained in:
@@ -15,6 +15,7 @@ import Flex from "components/Flex";
|
||||
import Highlight from "components/Highlight";
|
||||
import StarButton, { AnimatedStar } from "components/Star";
|
||||
import Tooltip from "components/Tooltip";
|
||||
import useBoolean from "hooks/useBoolean";
|
||||
import useCurrentTeam from "hooks/useCurrentTeam";
|
||||
import useCurrentUser from "hooks/useCurrentUser";
|
||||
import useStores from "hooks/useStores";
|
||||
@@ -46,7 +47,7 @@ function DocumentListItem(props: Props, ref) {
|
||||
const { policies } = useStores();
|
||||
const currentUser = useCurrentUser();
|
||||
const currentTeam = useCurrentTeam();
|
||||
const [menuOpen, setMenuOpen] = React.useState(false);
|
||||
const [menuOpen, handleMenuOpen, handleMenuClose] = useBoolean();
|
||||
const {
|
||||
document,
|
||||
showNestedDocuments,
|
||||
@@ -66,9 +67,6 @@ function DocumentListItem(props: Props, ref) {
|
||||
!document.isDraft && !document.isArchived && !document.isTemplate;
|
||||
const can = policies.abilities(currentTeam.id);
|
||||
|
||||
const handleMenuOpen = React.useCallback(() => setMenuOpen(true), []);
|
||||
const handleMenuClosed = React.useCallback(() => setMenuOpen(false), []);
|
||||
|
||||
return (
|
||||
<DocumentLink
|
||||
ref={ref}
|
||||
@@ -147,7 +145,7 @@ function DocumentListItem(props: Props, ref) {
|
||||
document={document}
|
||||
showPin={showPin}
|
||||
onOpen={handleMenuOpen}
|
||||
onClose={handleMenuClosed}
|
||||
onClose={handleMenuClose}
|
||||
modal={false}
|
||||
/>
|
||||
</Actions>
|
||||
|
||||
@@ -12,6 +12,7 @@ import DropCursor from "./DropCursor";
|
||||
import DropToImport from "./DropToImport";
|
||||
import EditableTitle from "./EditableTitle";
|
||||
import SidebarLink from "./SidebarLink";
|
||||
import useBoolean from "hooks/useBoolean";
|
||||
import useStores from "hooks/useStores";
|
||||
import CollectionMenu from "menus/CollectionMenu";
|
||||
import CollectionSortMenu from "menus/CollectionSortMenu";
|
||||
@@ -35,7 +36,7 @@ function CollectionLink({
|
||||
isDraggingAnyCollection,
|
||||
onChangeDragging,
|
||||
}: Props) {
|
||||
const [menuOpen, setMenuOpen] = React.useState(false);
|
||||
const [menuOpen, handleMenuOpen, handleMenuClose] = useBoolean();
|
||||
|
||||
const handleTitleChange = React.useCallback(
|
||||
async (name: string) => {
|
||||
@@ -163,14 +164,14 @@ function CollectionLink({
|
||||
{can.update && (
|
||||
<CollectionSortMenuWithMargin
|
||||
collection={collection}
|
||||
onOpen={() => setMenuOpen(true)}
|
||||
onClose={() => setMenuOpen(false)}
|
||||
onOpen={handleMenuOpen}
|
||||
onClose={handleMenuClose}
|
||||
/>
|
||||
)}
|
||||
<CollectionMenu
|
||||
collection={collection}
|
||||
onOpen={() => setMenuOpen(true)}
|
||||
onClose={() => setMenuOpen(false)}
|
||||
onOpen={handleMenuOpen}
|
||||
onClose={handleMenuClose}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import DropCursor from "./DropCursor";
|
||||
import DropToImport from "./DropToImport";
|
||||
import EditableTitle from "./EditableTitle";
|
||||
import SidebarLink from "./SidebarLink";
|
||||
import useBoolean from "hooks/useBoolean";
|
||||
import useStores from "hooks/useStores";
|
||||
import DocumentMenu from "menus/DocumentMenu";
|
||||
import { type NavigationNode } from "types";
|
||||
@@ -120,7 +121,7 @@ function DocumentLink(
|
||||
[documents, document]
|
||||
);
|
||||
|
||||
const [menuOpen, setMenuOpen] = React.useState(false);
|
||||
const [menuOpen, handleMenuOpen, handleMenuClose] = useBoolean();
|
||||
const isMoving = documents.movingDocumentId === node.id;
|
||||
const manualSort = collection?.sort.field === "index";
|
||||
|
||||
@@ -245,8 +246,8 @@ function DocumentLink(
|
||||
<Fade>
|
||||
<DocumentMenu
|
||||
document={document}
|
||||
onOpen={() => setMenuOpen(true)}
|
||||
onClose={() => setMenuOpen(false)}
|
||||
onOpen={handleMenuOpen}
|
||||
onClose={handleMenuClose}
|
||||
/>
|
||||
</Fade>
|
||||
) : undefined
|
||||
|
||||
23
app/hooks/useBoolean.js
Normal file
23
app/hooks/useBoolean.js
Normal file
@@ -0,0 +1,23 @@
|
||||
// @flow
|
||||
import * as React from "react";
|
||||
|
||||
type InitialState = boolean | (() => boolean);
|
||||
|
||||
/**
|
||||
* React hook to manage booleans
|
||||
*
|
||||
* @param initialState the initial boolean state value
|
||||
*/
|
||||
export default function useBoolean(initialState: InitialState = false) {
|
||||
const [value, setValue] = React.useState(initialState);
|
||||
|
||||
const setTrue = React.useCallback(() => {
|
||||
setValue(true);
|
||||
}, []);
|
||||
|
||||
const setFalse = React.useCallback(() => {
|
||||
setValue(false);
|
||||
}, []);
|
||||
|
||||
return [value, setTrue, setFalse];
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import MenuItem, { MenuAnchor } from "components/ContextMenu/MenuItem";
|
||||
import Separator from "components/ContextMenu/Separator";
|
||||
import Flex from "components/Flex";
|
||||
import Guide from "components/Guide";
|
||||
import useBoolean from "hooks/useBoolean";
|
||||
import usePrevious from "hooks/usePrevious";
|
||||
import useStores from "hooks/useStores";
|
||||
|
||||
@@ -78,9 +79,11 @@ function AccountMenu(props: Props) {
|
||||
const { auth, ui } = useStores();
|
||||
const previousTheme = usePrevious(ui.theme);
|
||||
const { t } = useTranslation();
|
||||
const [keyboardShortcutsOpen, setKeyboardShortcutsOpen] = React.useState(
|
||||
false
|
||||
);
|
||||
const [
|
||||
keyboardShortcutsOpen,
|
||||
handleKeyboardShortcutsOpen,
|
||||
handleKeyboardShortcutsClose,
|
||||
] = useBoolean();
|
||||
|
||||
React.useEffect(() => {
|
||||
if (ui.theme !== previousTheme) {
|
||||
@@ -92,7 +95,7 @@ function AccountMenu(props: Props) {
|
||||
<>
|
||||
<Guide
|
||||
isOpen={keyboardShortcutsOpen}
|
||||
onRequestClose={() => setKeyboardShortcutsOpen(false)}
|
||||
onRequestClose={handleKeyboardShortcutsClose}
|
||||
title={t("Keyboard shortcuts")}
|
||||
>
|
||||
<KeyboardShortcuts />
|
||||
@@ -102,7 +105,7 @@ function AccountMenu(props: Props) {
|
||||
<MenuItem {...menu} as={Link} to={settings()}>
|
||||
{t("Settings")}
|
||||
</MenuItem>
|
||||
<MenuItem {...menu} onClick={() => setKeyboardShortcutsOpen(true)}>
|
||||
<MenuItem {...menu} onClick={handleKeyboardShortcutsOpen}>
|
||||
{t("Keyboard shortcuts")}
|
||||
</MenuItem>
|
||||
<MenuItem {...menu} href={developers()} target="_blank">
|
||||
|
||||
@@ -39,6 +39,7 @@ import Tabs from "components/Tabs";
|
||||
import Tooltip from "components/Tooltip";
|
||||
import Collection from "../models/Collection";
|
||||
import { updateCollectionUrl } from "../utils/routeHelpers";
|
||||
import useBoolean from "hooks/useBoolean";
|
||||
import useCurrentTeam from "hooks/useCurrentTeam";
|
||||
import useImportDocument from "hooks/useImportDocument";
|
||||
import useStores from "hooks/useStores";
|
||||
@@ -54,7 +55,11 @@ function CollectionScene() {
|
||||
const team = useCurrentTeam();
|
||||
const [isFetching, setFetching] = React.useState();
|
||||
const [error, setError] = React.useState();
|
||||
const [permissionsModalOpen, setPermissionsModalOpen] = React.useState(false);
|
||||
const [
|
||||
permissionsModalOpen,
|
||||
handlePermissionsModalOpen,
|
||||
handlePermissionsModalClose,
|
||||
] = useBoolean();
|
||||
|
||||
const id = params.id || "";
|
||||
const collection: ?Collection =
|
||||
@@ -102,14 +107,6 @@ function CollectionScene() {
|
||||
load();
|
||||
}, [collections, isFetching, collection, error, id, can]);
|
||||
|
||||
const handlePermissionsModalOpen = React.useCallback(() => {
|
||||
setPermissionsModalOpen(true);
|
||||
}, []);
|
||||
|
||||
const handlePermissionsModalClose = React.useCallback(() => {
|
||||
setPermissionsModalOpen(false);
|
||||
}, []);
|
||||
|
||||
const handleRejection = React.useCallback(() => {
|
||||
ui.showToast(
|
||||
t("Document not supported – try Markdown, Plain text, HTML, or Word"),
|
||||
|
||||
@@ -17,6 +17,7 @@ import AddGroupsToCollection from "./AddGroupsToCollection";
|
||||
import AddPeopleToCollection from "./AddPeopleToCollection";
|
||||
import CollectionGroupMemberListItem from "./components/CollectionGroupMemberListItem";
|
||||
import MemberListItem from "./components/MemberListItem";
|
||||
import useBoolean from "hooks/useBoolean";
|
||||
import useCurrentUser from "hooks/useCurrentUser";
|
||||
import useStores from "hooks/useStores";
|
||||
|
||||
@@ -34,8 +35,16 @@ function CollectionPermissions({ collection }: Props) {
|
||||
users,
|
||||
groups,
|
||||
} = useStores();
|
||||
const [addGroupModalOpen, setAddGroupModalOpen] = React.useState(false);
|
||||
const [addMemberModalOpen, setAddMemberModalOpen] = React.useState(false);
|
||||
const [
|
||||
addGroupModalOpen,
|
||||
handleAddGroupModalOpen,
|
||||
handleAddGroupModalClose,
|
||||
] = useBoolean();
|
||||
const [
|
||||
addMemberModalOpen,
|
||||
handleAddMemberModalOpen,
|
||||
handleAddMemberModalClose,
|
||||
] = useBoolean();
|
||||
|
||||
const handleRemoveUser = React.useCallback(
|
||||
async (user) => {
|
||||
@@ -183,7 +192,7 @@ function CollectionPermissions({ collection }: Props) {
|
||||
<Actions>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => setAddGroupModalOpen(true)}
|
||||
onClick={handleAddGroupModalOpen}
|
||||
icon={<PlusIcon />}
|
||||
neutral
|
||||
>
|
||||
@@ -191,7 +200,7 @@ function CollectionPermissions({ collection }: Props) {
|
||||
</Button>{" "}
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => setAddMemberModalOpen(true)}
|
||||
onClick={handleAddMemberModalOpen}
|
||||
icon={<PlusIcon />}
|
||||
neutral
|
||||
>
|
||||
@@ -244,24 +253,24 @@ function CollectionPermissions({ collection }: Props) {
|
||||
title={t(`Add groups to {{ collectionName }}`, {
|
||||
collectionName: collection.name,
|
||||
})}
|
||||
onRequestClose={() => setAddGroupModalOpen(false)}
|
||||
onRequestClose={handleAddGroupModalClose}
|
||||
isOpen={addGroupModalOpen}
|
||||
>
|
||||
<AddGroupsToCollection
|
||||
collection={collection}
|
||||
onSubmit={() => setAddGroupModalOpen(false)}
|
||||
onSubmit={handleAddGroupModalClose}
|
||||
/>
|
||||
</Modal>
|
||||
<Modal
|
||||
title={t(`Add people to {{ collectionName }}`, {
|
||||
collectionName: collection.name,
|
||||
})}
|
||||
onRequestClose={() => setAddMemberModalOpen(false)}
|
||||
onRequestClose={handleAddMemberModalClose}
|
||||
isOpen={addMemberModalOpen}
|
||||
>
|
||||
<AddPeopleToCollection
|
||||
collection={collection}
|
||||
onSubmit={() => setAddMemberModalOpen(false)}
|
||||
onSubmit={handleAddMemberModalClose}
|
||||
/>
|
||||
</Modal>
|
||||
</Flex>
|
||||
|
||||
@@ -8,20 +8,15 @@ import KeyboardShortcuts from "scenes/KeyboardShortcuts";
|
||||
import Guide from "components/Guide";
|
||||
import NudeButton from "components/NudeButton";
|
||||
import Tooltip from "components/Tooltip";
|
||||
import useBoolean from "hooks/useBoolean";
|
||||
|
||||
function KeyboardShortcutsButton() {
|
||||
const { t } = useTranslation();
|
||||
const [keyboardShortcutsOpen, setKeyboardShortcutsOpen] = React.useState(
|
||||
false
|
||||
);
|
||||
|
||||
const handleCloseKeyboardShortcuts = React.useCallback(() => {
|
||||
setKeyboardShortcutsOpen(false);
|
||||
}, []);
|
||||
|
||||
const handleOpenKeyboardShortcuts = React.useCallback(() => {
|
||||
setKeyboardShortcutsOpen(true);
|
||||
}, []);
|
||||
const [
|
||||
keyboardShortcutsOpen,
|
||||
handleOpenKeyboardShortcuts,
|
||||
handleCloseKeyboardShortcuts,
|
||||
] = useBoolean();
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -14,6 +14,7 @@ import Modal from "components/Modal";
|
||||
import PaginatedList from "components/PaginatedList";
|
||||
import Scene from "components/Scene";
|
||||
import Subheading from "components/Subheading";
|
||||
import useBoolean from "hooks/useBoolean";
|
||||
import useCurrentTeam from "hooks/useCurrentTeam";
|
||||
import useStores from "hooks/useStores";
|
||||
import GroupMenu from "menus/GroupMenu";
|
||||
@@ -23,15 +24,11 @@ function Groups() {
|
||||
const { policies, groups } = useStores();
|
||||
const team = useCurrentTeam();
|
||||
const can = policies.abilities(team.id);
|
||||
const [newGroupModalOpen, setNewGroupModalOpen] = React.useState(false);
|
||||
|
||||
const handleNewGroupModalOpen = React.useCallback(() => {
|
||||
setNewGroupModalOpen(true);
|
||||
}, []);
|
||||
|
||||
const handleNewGroupModalClose = React.useCallback(() => {
|
||||
setNewGroupModalOpen(false);
|
||||
}, []);
|
||||
const [
|
||||
newGroupModalOpen,
|
||||
handleNewGroupModalOpen,
|
||||
handleNewGroupModalClose,
|
||||
] = useBoolean();
|
||||
|
||||
return (
|
||||
<Scene
|
||||
|
||||
@@ -18,6 +18,7 @@ import Modal from "components/Modal";
|
||||
import Scene from "components/Scene";
|
||||
import PeopleTable from "./components/PeopleTable";
|
||||
import UserStatusFilter from "./components/UserStatusFilter";
|
||||
import useBoolean from "hooks/useBoolean";
|
||||
import useCurrentTeam from "hooks/useCurrentTeam";
|
||||
import useQuery from "hooks/useQuery";
|
||||
import useStores from "hooks/useStores";
|
||||
@@ -26,7 +27,11 @@ function People(props) {
|
||||
const topRef = React.useRef();
|
||||
const location = useLocation();
|
||||
const history = useHistory();
|
||||
const [inviteModalOpen, setInviteModalOpen] = React.useState(false);
|
||||
const [
|
||||
inviteModalOpen,
|
||||
handleInviteModalOpen,
|
||||
handleInviteModalClose,
|
||||
] = useBoolean();
|
||||
const team = useCurrentTeam();
|
||||
const { users, policies } = useStores();
|
||||
const { t } = useTranslation();
|
||||
@@ -96,14 +101,6 @@ function People(props) {
|
||||
userIds,
|
||||
]);
|
||||
|
||||
const handleInviteModalOpen = React.useCallback(() => {
|
||||
setInviteModalOpen(true);
|
||||
}, []);
|
||||
|
||||
const handleInviteModalClose = React.useCallback(() => {
|
||||
setInviteModalOpen(false);
|
||||
}, []);
|
||||
|
||||
const handleFilter = React.useCallback(
|
||||
(filter) => {
|
||||
if (filter) {
|
||||
|
||||
@@ -13,6 +13,7 @@ import PaginatedList from "components/PaginatedList";
|
||||
import Scene from "components/Scene";
|
||||
import Subheading from "components/Subheading";
|
||||
import TokenListItem from "./components/TokenListItem";
|
||||
import useBoolean from "hooks/useBoolean";
|
||||
import useCurrentTeam from "hooks/useCurrentTeam";
|
||||
import useStores from "hooks/useStores";
|
||||
|
||||
@@ -20,17 +21,9 @@ function Tokens() {
|
||||
const team = useCurrentTeam();
|
||||
const { t } = useTranslation();
|
||||
const { apiKeys, policies } = useStores();
|
||||
const [newModalOpen, setNewModalOpen] = React.useState(false);
|
||||
const [newModalOpen, handleNewModalOpen, handleNewModalClose] = useBoolean();
|
||||
const can = policies.abilities(team.id);
|
||||
|
||||
const handleNewModalOpen = React.useCallback(() => {
|
||||
setNewModalOpen(true);
|
||||
}, []);
|
||||
|
||||
const handleNewModalClose = React.useCallback(() => {
|
||||
setNewModalOpen(false);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Scene
|
||||
title={t("API Tokens")}
|
||||
|
||||
Reference in New Issue
Block a user