Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState } from 'react';
import { useEffect, useState, useRef } from 'react';
import { FieldExtensionComponentProps } from '@backstage/plugin-scaffolder-react';
import { Typography, Box } from '@material-ui/core';
import {
Expand Down Expand Up @@ -45,6 +45,10 @@ export const BuildWorkflowParameters = ({
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);

// Track workflow changes to force Form remount only when workflow actually changes
const [resetKey, setResetKey] = useState(0);
const prevWorkflowRef = useRef<string | undefined>(undefined);

const discoveryApi = useApi(discoveryApiRef);
const identityApi = useApi(identityApiRef);

Expand All @@ -53,6 +57,18 @@ export const BuildWorkflowParameters = ({
const selectedWorkflowName = formContext?.formData?.workflow_name;
const organizationName = formContext?.formData?.organization_name;

// Increment resetKey only when workflow actually changes
// This forces Form remount only on workflow change, not on every render
useEffect(() => {
if (
prevWorkflowRef.current !== undefined &&
prevWorkflowRef.current !== selectedWorkflowName
) {
setResetKey(prev => prev + 1);
}
prevWorkflowRef.current = selectedWorkflowName;
}, [selectedWorkflowName]);

// Fetch workflow schema when workflow selection changes
useEffect(() => {
let ignore = false;
Expand Down Expand Up @@ -124,20 +140,27 @@ export const BuildWorkflowParameters = ({
};
}, [selectedWorkflowName, organizationName, discoveryApi, identityApi]);

// Sync schema to formData when workflow schema changes
// Sync schema to formData when workflow changes (not just when schema loads)
useEffect(() => {
if (workflowSchema) {
// Update formData to include the schema for validation
if (workflowSchema && resetKey > 0) {
// Clear old parameters only when workflow actually changes (resetKey increments)
// This prevents clearing when user navigates back to this step
onChange({
parameters: {},
schema: workflowSchema,
});
} else if (workflowSchema && resetKey === 0 && !formData?.schema) {
// First time loading: initialize with existing or empty parameters
onChange({
parameters: formData?.parameters || {},
schema: workflowSchema,
});
}
// We intentionally only depend on workflowSchema to avoid infinite loop.
// We intentionally only depend on workflowSchema and resetKey.
// Adding onChange or formData would cause infinite re-renders:
// onChange -> formData changes -> useEffect triggers -> onChange -> loop
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [workflowSchema]);
}, [workflowSchema, resetKey]);

// Handle form data changes from RJSF
const handleFormChange = (changeEvent: any) => {
Expand Down Expand Up @@ -190,6 +213,7 @@ export const BuildWorkflowParameters = ({
Workflow Parameters
</Typography>
<Form
key={resetKey}
schema={workflowSchema}
uiSchema={uiSchema}
formData={formData?.parameters || {}}
Expand Down