mirror of
https://github.com/FlowiseAI/Flowise.git
synced 2026-10-12 02:02:17 +00:00
fix (AgentFlow) - generate ArrayInput item keys synchronously to prevent missing React keys (#6001)
* Fix to remove useEffect * Fix gemini comment
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { type ComponentType, useCallback, useEffect, useMemo, useRef } from 'react'
|
||||
import { type ComponentType, useCallback, useMemo, useRef, useState } from 'react'
|
||||
|
||||
import { Box, Button, Chip, IconButton } from '@mui/material'
|
||||
import { useTheme } from '@mui/material/styles'
|
||||
@@ -42,16 +42,33 @@ export function ArrayInput({
|
||||
[data.inputValues, inputParam.name]
|
||||
)
|
||||
|
||||
// Stable keys for array items — avoids using index as React key
|
||||
// Stable keys for array items — avoids using index as React key.
|
||||
// Keys are held in state so they persist across renders. A local variable
|
||||
// (`effectiveKeys`) is used for the current render pass so that newly
|
||||
// generated keys are available immediately (setState alone would only
|
||||
// take effect on the *next* render, leaving keys undefined in this one).
|
||||
const idCounterRef = useRef(0)
|
||||
const itemKeysRef = useRef<string[]>([])
|
||||
|
||||
// Grow keys array when new items appear (e.g. on mount or external data changes)
|
||||
useEffect(() => {
|
||||
while (itemKeysRef.current.length < arrayItems.length) {
|
||||
itemKeysRef.current.push(`item-${idCounterRef.current++}`)
|
||||
const [itemKeys, setItemKeys] = useState<string[]>(() => {
|
||||
const initial: string[] = []
|
||||
while (initial.length < arrayItems.length) {
|
||||
initial.push(`item-${idCounterRef.current++}`)
|
||||
}
|
||||
}, [arrayItems.length])
|
||||
return initial
|
||||
})
|
||||
|
||||
let effectiveKeys = itemKeys
|
||||
if (effectiveKeys.length < arrayItems.length) {
|
||||
const nextKeys = [...effectiveKeys]
|
||||
while (nextKeys.length < arrayItems.length) {
|
||||
nextKeys.push(`item-${idCounterRef.current++}`)
|
||||
}
|
||||
setItemKeys(nextKeys)
|
||||
effectiveKeys = nextKeys
|
||||
} else if (effectiveKeys.length > arrayItems.length) {
|
||||
const trimmed = effectiveKeys.slice(0, arrayItems.length)
|
||||
setItemKeys(trimmed)
|
||||
effectiveKeys = trimmed
|
||||
}
|
||||
|
||||
// Use pre-computed itemParameters
|
||||
// Falls back to raw field definitions for nested arrays without show/hide conditions.
|
||||
@@ -113,7 +130,7 @@ export function ArrayInput({
|
||||
const handleDeleteItem = useCallback(
|
||||
(indexToDelete: number) => {
|
||||
const updatedArrayItems = arrayItems.filter((_, i) => i !== indexToDelete)
|
||||
itemKeysRef.current.splice(indexToDelete, 1)
|
||||
setItemKeys((prev) => prev.filter((_, i) => i !== indexToDelete))
|
||||
|
||||
// Notify parent of change (parent will update props, causing re-render)
|
||||
onDataChange?.({ inputParam, newValue: updatedArrayItems })
|
||||
@@ -145,7 +162,7 @@ export function ArrayInput({
|
||||
|
||||
return (
|
||||
<Box
|
||||
key={itemKeysRef.current[index]}
|
||||
key={effectiveKeys[index]}
|
||||
sx={{
|
||||
p: 2,
|
||||
mt: 2,
|
||||
|
||||
Reference in New Issue
Block a user