Fully deprecate old recoil (#18210)
## Summary Removes the `recoil` dependency entirely from `package.json` and `twenty-front/package.json`, completing the migration to Jotai as the sole state management library. Removes all Recoil infrastructure: `RecoilRoot` wrapper from `App.tsx` and test decorators, `RecoilDebugObserver`, Recoil-specific ESLint rules (`use-getLoadable-and-getValue-to-get-atoms`, `useRecoilCallback-has-dependency-array`), and legacy Recoil utility hooks/types (`useRecoilComponentState`, `useRecoilComponentValue`, `createComponentState`, `createFamilyState`, `getSnapshotValue`, `cookieStorageEffect`, `localStorageEffect`, etc.). Renames all `V2`-suffixed Jotai state files and types to their canonical names (e.g., `ComponentStateV2` -> `ComponentState`, `agentChatInputStateV2` -> `agentChatInputState`, `SelectorCallbacksV2` -> `SelectorCallbacks`), and removes the now-redundant V1 counterparts. Updates ~433 files across the codebase to use the renamed Jotai imports, remove Recoil imports, and clean up test wrappers (`RecoilRootDecorator` -> `JotaiRootDecorator`).
This commit is contained in:
+2
-2
@@ -9,7 +9,7 @@ import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/use
|
||||
import { useDeleteStep } from '@/workflow/workflow-steps/hooks/useDeleteStep';
|
||||
import { useDuplicateStep } from '@/workflow/workflow-steps/hooks/useDuplicateStep';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { workflowAiAgentActionAgentStateV2 } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentActionAgentStateV2';
|
||||
import { workflowAiAgentActionAgentState } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentActionAgentState';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useId } from 'react';
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
@@ -45,7 +45,7 @@ export const WorkflowStepFooter = ({
|
||||
const { deleteStep } = useDeleteStep();
|
||||
const navigateSettings = useNavigateSettings();
|
||||
const workflowAiAgentActionAgent = useAtomStateValue(
|
||||
workflowAiAgentActionAgentStateV2,
|
||||
workflowAiAgentActionAgentState,
|
||||
);
|
||||
const shouldPinDeleteButton =
|
||||
!isDefined(additionalActions) || additionalActions.length === 0;
|
||||
|
||||
+7
-10
@@ -1,5 +1,4 @@
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
import { useCreateStep } from '@/workflow/workflow-steps/hooks/useCreateStep';
|
||||
|
||||
@@ -40,15 +39,13 @@ const wrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
'workflow-visualizer-instance-id';
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<WorkflowVisualizerComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: workflowVisualizerComponentInstanceId,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WorkflowVisualizerComponentInstanceContext.Provider>
|
||||
</RecoilRoot>
|
||||
<WorkflowVisualizerComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: workflowVisualizerComponentInstanceId,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WorkflowVisualizerComponentInstanceContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
+7
-10
@@ -2,7 +2,6 @@ import React from 'react';
|
||||
|
||||
import { useDeleteStep } from '@/workflow/workflow-steps/hooks/useDeleteStep';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
|
||||
const mockDeleteWorkflowVersionStep = jest.fn();
|
||||
@@ -55,15 +54,13 @@ const wrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
'workflow-visualizer-instance-id';
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<WorkflowVisualizerComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: workflowVisualizerComponentInstanceId,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WorkflowVisualizerComponentInstanceContext.Provider>
|
||||
</RecoilRoot>
|
||||
<WorkflowVisualizerComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: workflowVisualizerComponentInstanceId,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WorkflowVisualizerComponentInstanceContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
+7
-10
@@ -1,6 +1,5 @@
|
||||
import { useDuplicateStep } from '@/workflow/workflow-steps/hooks/useDuplicateStep';
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
|
||||
const mockGetUpdatableWorkflowVersion = jest.fn();
|
||||
@@ -38,15 +37,13 @@ const wrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
'workflow-visualizer-instance-id';
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<WorkflowVisualizerComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: workflowVisualizerComponentInstanceId,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WorkflowVisualizerComponentInstanceContext.Provider>
|
||||
</RecoilRoot>
|
||||
<WorkflowVisualizerComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: workflowVisualizerComponentInstanceId,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WorkflowVisualizerComponentInstanceContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
+6
-6
@@ -5,9 +5,9 @@ import { type WorkflowAiAgentAction } from '@/workflow/types/Workflow';
|
||||
import { useWorkflowAiAgentPermissionActions } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/hooks/useWorkflowAiAgentPermissionActions';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { workflowAiAgentActionAgentStateV2 } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentActionAgentStateV2';
|
||||
import { workflowAiAgentPermissionsIsAddingPermissionStateV2 } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentPermissionsIsAddingPermissionStateV2';
|
||||
import { workflowAiAgentPermissionsSelectedObjectIdStateV2 } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentPermissionsSelectedObjectIdStateV2';
|
||||
import { workflowAiAgentActionAgentState } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentActionAgentState';
|
||||
import { workflowAiAgentPermissionsIsAddingPermissionState } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentPermissionsIsAddingPermissionState';
|
||||
import { workflowAiAgentPermissionsSelectedObjectIdState } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentPermissionsSelectedObjectIdState';
|
||||
import styled from '@emotion/styled';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useState } from 'react';
|
||||
@@ -76,17 +76,17 @@ export const WorkflowAiAgentPermissionsTab = ({
|
||||
refetchAgent,
|
||||
}: WorkflowAiAgentPermissionsTabProps) => {
|
||||
const workflowAiAgentActionAgent = useAtomStateValue(
|
||||
workflowAiAgentActionAgentStateV2,
|
||||
workflowAiAgentActionAgentState,
|
||||
);
|
||||
|
||||
const [
|
||||
workflowAiAgentPermissionsSelectedObjectId,
|
||||
setWorkflowAiAgentPermissionsSelectedObjectId,
|
||||
] = useAtomState(workflowAiAgentPermissionsSelectedObjectIdStateV2);
|
||||
] = useAtomState(workflowAiAgentPermissionsSelectedObjectIdState);
|
||||
const [
|
||||
workflowAiAgentPermissionsIsAddingPermission,
|
||||
setWorkflowAiAgentPermissionsIsAddingPermission,
|
||||
] = useAtomState(workflowAiAgentPermissionsIsAddingPermissionStateV2);
|
||||
] = useAtomState(workflowAiAgentPermissionsIsAddingPermissionState);
|
||||
|
||||
const { alphaSortedActiveNonSystemObjectMetadataItems: objectMetadataItems } =
|
||||
useFilteredObjectMetadataItems();
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { FormTextFieldInput } from '@/object-record/record-field/ui/form-types/components/FormTextFieldInput';
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { workflowAiAgentActionAgentStateV2 } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentActionAgentStateV2';
|
||||
import { workflowAiAgentActionAgentState } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentActionAgentState';
|
||||
import { WorkflowVariablePicker } from '@/workflow/workflow-variables/components/WorkflowVariablePicker';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
@@ -33,7 +33,7 @@ export const WorkflowAiAgentPromptTab = ({
|
||||
onResponseFormatChange,
|
||||
}: WorkflowAiAgentPromptTabProps) => {
|
||||
const workflowAiAgentActionAgent = useAtomStateValue(
|
||||
workflowAiAgentActionAgentStateV2,
|
||||
workflowAiAgentActionAgentState,
|
||||
);
|
||||
return (
|
||||
<>
|
||||
|
||||
+4
-4
@@ -13,8 +13,8 @@ import { WorkflowAiAgentPermissionsTab } from '@/workflow/workflow-steps/workflo
|
||||
import { WORKFLOW_AI_AGENT_TABS } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/constants/WorkflowAiAgentTabs';
|
||||
import { useResetWorkflowAiAgentPermissionsStateOnCommandMenuClose } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/hooks/useResetWorkflowAiAgentPermissionsStateOnCommandMenuClose';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
import { workflowAiAgentActionAgentStateV2 } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentActionAgentStateV2';
|
||||
import { workflowAiAgentPermissionsIsAddingPermissionStateV2 } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentPermissionsIsAddingPermissionStateV2';
|
||||
import { workflowAiAgentActionAgentState } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentActionAgentState';
|
||||
import { workflowAiAgentPermissionsIsAddingPermissionState } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentPermissionsIsAddingPermissionState';
|
||||
import styled from '@emotion/styled';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import {
|
||||
@@ -66,7 +66,7 @@ export const WorkflowEditActionAiAgent = ({
|
||||
const componentInstanceId = `${WORKFLOW_AI_AGENT_TAB_LIST_COMPONENT_ID}-${action.id}`;
|
||||
const agentId = action.settings.input.agentId;
|
||||
const [workflowAiAgentActionAgent, setWorkflowAiAgentActionAgent] =
|
||||
useAtomState(workflowAiAgentActionAgentStateV2);
|
||||
useAtomState(workflowAiAgentActionAgentState);
|
||||
const { loading: agentLoading, refetch: refetchAgent } = useFindOneAgentQuery(
|
||||
{
|
||||
variables: { id: agentId || '' },
|
||||
@@ -217,7 +217,7 @@ export const WorkflowEditActionAiAgent = ({
|
||||
const [
|
||||
workflowAiAgentPermissionsIsAddingPermission,
|
||||
setWorkflowAiAgentPermissionsIsAddingPermission,
|
||||
] = useAtomState(workflowAiAgentPermissionsIsAddingPermissionStateV2);
|
||||
] = useAtomState(workflowAiAgentPermissionsIsAddingPermissionState);
|
||||
|
||||
const role = rolesData?.getRoles.find(
|
||||
(item) => item.id === workflowAiAgentActionAgent?.roleId,
|
||||
|
||||
+6
-6
@@ -1,17 +1,17 @@
|
||||
import { useListenToSidePanelClosing } from '@/ui/layout/right-drawer/hooks/useListenToSidePanelClosing';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
import { workflowAiAgentActionAgentStateV2 } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentActionAgentStateV2';
|
||||
import { workflowAiAgentPermissionsIsAddingPermissionStateV2 } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentPermissionsIsAddingPermissionStateV2';
|
||||
import { workflowAiAgentPermissionsSelectedObjectIdStateV2 } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentPermissionsSelectedObjectIdStateV2';
|
||||
import { workflowAiAgentActionAgentState } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentActionAgentState';
|
||||
import { workflowAiAgentPermissionsIsAddingPermissionState } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentPermissionsIsAddingPermissionState';
|
||||
import { workflowAiAgentPermissionsSelectedObjectIdState } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentPermissionsSelectedObjectIdState';
|
||||
|
||||
export const useResetWorkflowAiAgentPermissionsStateOnCommandMenuClose = () => {
|
||||
const setSelectedObjectId = useSetAtomState(
|
||||
workflowAiAgentPermissionsSelectedObjectIdStateV2,
|
||||
workflowAiAgentPermissionsSelectedObjectIdState,
|
||||
);
|
||||
const setIsAddingPermission = useSetAtomState(
|
||||
workflowAiAgentPermissionsIsAddingPermissionStateV2,
|
||||
workflowAiAgentPermissionsIsAddingPermissionState,
|
||||
);
|
||||
const setAgentState = useSetAtomState(workflowAiAgentActionAgentStateV2);
|
||||
const setAgentState = useSetAtomState(workflowAiAgentActionAgentState);
|
||||
|
||||
const resetPermissionState = () => {
|
||||
setSelectedObjectId(undefined);
|
||||
|
||||
+7
-7
@@ -5,9 +5,9 @@ import { useSettingsRolePermissionFlagConfig } from '@/settings/roles/role-permi
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { CRUD_PERMISSIONS } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/constants/WorkflowAiAgentCrudPermissions';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
import { workflowAiAgentActionAgentStateV2 } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentActionAgentStateV2';
|
||||
import { workflowAiAgentPermissionsIsAddingPermissionStateV2 } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentPermissionsIsAddingPermissionStateV2';
|
||||
import { workflowAiAgentPermissionsSelectedObjectIdStateV2 } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentPermissionsSelectedObjectIdStateV2';
|
||||
import { workflowAiAgentActionAgentState } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentActionAgentState';
|
||||
import { workflowAiAgentPermissionsIsAddingPermissionState } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentPermissionsIsAddingPermissionState';
|
||||
import { workflowAiAgentPermissionsSelectedObjectIdState } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/states/workflowAiAgentPermissionsSelectedObjectIdState';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useMemo } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@@ -37,7 +37,7 @@ export const useWorkflowAiAgentPermissionActions = ({
|
||||
}: UseWorkflowAiAgentPermissionActionsParams) => {
|
||||
const { enqueueSuccessSnackBar } = useSnackBar();
|
||||
const [workflowAiAgentActionAgent, setWorkflowAiAgentActionAgent] =
|
||||
useAtomState(workflowAiAgentActionAgentStateV2);
|
||||
useAtomState(workflowAiAgentActionAgentState);
|
||||
const { alphaSortedActiveNonSystemObjectMetadataItems: objectMetadataItems } =
|
||||
useFilteredObjectMetadataItems();
|
||||
const settingsPermissionsConfig = useSettingsRolePermissionFlagConfig({
|
||||
@@ -48,10 +48,10 @@ export const useWorkflowAiAgentPermissionActions = ({
|
||||
});
|
||||
|
||||
const [, setWorkflowAiAgentPermissionsSelectedObjectId] = useAtomState(
|
||||
workflowAiAgentPermissionsSelectedObjectIdStateV2,
|
||||
workflowAiAgentPermissionsSelectedObjectIdState,
|
||||
);
|
||||
const [, setWorkflowAiAgentPermissionsIsAddingPermission] = useAtomState(
|
||||
workflowAiAgentPermissionsIsAddingPermissionStateV2,
|
||||
workflowAiAgentPermissionsIsAddingPermissionState,
|
||||
);
|
||||
|
||||
const [createRole] = useCreateOneRoleMutation();
|
||||
@@ -118,7 +118,7 @@ export const useWorkflowAiAgentPermissionActions = ({
|
||||
|
||||
const { refetchedAgent } = await refetchAgentAndRoles();
|
||||
|
||||
// Update Recoil state with the refetched agent to ensure roleId is available
|
||||
// Update state with the refetched agent to ensure roleId is available
|
||||
// Apollo's onCompleted is not called on refetch, so we need to update manually
|
||||
if (isDefined(refetchedAgent)) {
|
||||
setWorkflowAiAgentActionAgent(refetchedAgent);
|
||||
|
||||
+2
-2
@@ -2,9 +2,9 @@ import { type Agent } from '~/generated-metadata/graphql';
|
||||
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
|
||||
export const workflowAiAgentActionAgentStateV2 = createAtomState<
|
||||
export const workflowAiAgentActionAgentState = createAtomState<
|
||||
Agent | undefined
|
||||
>({
|
||||
key: 'workflowAiAgentActionAgentStateV2',
|
||||
key: 'workflowAiAgentActionAgentState',
|
||||
defaultValue: undefined,
|
||||
});
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
|
||||
export const workflowAiAgentPermissionsIsAddingPermissionStateV2 =
|
||||
export const workflowAiAgentPermissionsIsAddingPermissionState =
|
||||
createAtomState<boolean>({
|
||||
key: 'workflowAiAgentPermissionsIsAddingPermissionStateV2',
|
||||
key: 'workflowAiAgentPermissionsIsAddingPermissionState',
|
||||
defaultValue: false,
|
||||
});
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
|
||||
export const workflowAiAgentPermissionsSelectedObjectIdState = createAtomState<
|
||||
string | undefined
|
||||
>({
|
||||
key: 'workflowAiAgentPermissionsSelectedObjectIdState',
|
||||
defaultValue: undefined,
|
||||
});
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
|
||||
export const workflowAiAgentPermissionsSelectedObjectIdStateV2 =
|
||||
createAtomState<string | undefined>({
|
||||
key: 'workflowAiAgentPermissionsSelectedObjectIdStateV2',
|
||||
defaultValue: undefined,
|
||||
});
|
||||
+1
-2
@@ -3,7 +3,6 @@ import { type HttpRequestFormData } from '@/workflow/workflow-steps/workflow-act
|
||||
import { useMutation } from '@apollo/client';
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { resolveInput } from 'twenty-shared/utils';
|
||||
import { useTestHttpRequest } from '@/workflow/workflow-steps/workflow-actions/http-request-action/hooks/useTestHttpRequest';
|
||||
|
||||
@@ -87,7 +86,7 @@ describe('useTestHttpRequest', () => {
|
||||
};
|
||||
|
||||
const wrapper = ({ children }: { children: React.ReactNode }) =>
|
||||
React.createElement(RecoilRoot, null, children);
|
||||
React.createElement(React.Fragment, null, children);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
Reference in New Issue
Block a user