Este componente verifica si los campos se han cambiado desde el valor inicial y muestra la cantidad de campos modificados. Hay un useEffect para cada campo. Sería mejor con algo más SECO, pero no he descubierto cómo.
¿Hay alguna manera de hacer esto más rápido y mejor?
estados
const [unsavedChanges, setUnsavedChanges] = useState<Array<string>>([]); const [customField1, setCustomField1] = useState<string | null | undefined>( Data.field1 ); const [customField2, setCustomField2] = useState<string | null | undefined>( Data.field2 );Establecer estado de cambios no guardados
//Field 1 useEffect(() => { if ( (customField1 === Data.field1 || customField1 === null) && unsavedChanges?.includes('customfield1') ) { let filtered = unsavedChanges.filter( (item) => item !== 'customfield1' ); setUnsavedChanges(filtered); } else if ( customField1 === Data.field1 || unsavedChanges?.includes('customfield1') ) { return; } else { setUnsavedChanges([...unsavedChanges, 'customfield1']); } }, [customField1]); //Field 2 useEffect(() => { if ( (customField2 === Data.field2 || customField2 === null) && unsavedChanges?.includes('customfield2') ) { let filtered = unsavedChanges.filter( (item) => item !== 'customfield2' ); setUnsavedChanges(filtered); } else if ( customField2 === Data.field2 || unsavedChanges?.includes('customfield2') ) { return; } else { setUnsavedChanges([...unsavedChanges, 'customfield2']); } }, [customField2]);Devolver
<> <Input value={customField1} onChange={setCustomField1(e.target.value}/> <Input value={customField2} onChange={setCustomField2(e.target.value}/> <h1>{unsavedChanges.length} # of unsaved changes.</h1> <Button disabled={unsavedChanges.length > 0 ? false : true} label='Submit'/> </>creé un ejemplo de cómo hacerlo simple (en mi opinión). Fusioné los tres estados en uno. de esta manera puedo conseguir cada uno de forma más dinámica. luego creé en el controlador de cambios que maneja los cambios y hago todas las declaraciones if (con menos código). cada entrada activa el controlador de cambios en el cambio. y establece el estado de acuerdo con las declaraciones if. de esta manera podemos crear tantas entradas como queramos, solo necesitamos pasar los argumentos correctos al controlador de cambios y se encargará del resto por nosotros (y para asegurarnos de incluir un par de valores clave más en el estado)
estos son los datos ficticios para Data:
const Data = { field1: "abc", field2: "efg" };el estado:
const [generalState, setGeneralState] = useState({ unsavedChanges: [], customField1: "", customField2: "" });el manejador:
const changeTheState = (type, value, field, customField) => { //setting the values to the state. so we can fetch the values for the inputs and for later use setGeneralState((prev) => ({ ...prev, [type]: value })); // i narrowed down the if statements. now its only two. if ( value === Data[field] && generalState.unsavedChanges?.includes(customField) ) { return setGeneralState((prev) => { let filtered = prev.unsavedChanges.filter( (item) => item !== customField ); return { ...prev, unsavedChanges: filtered }; }); } if (!generalState.unsavedChanges?.includes(customField)) { setGeneralState((prev) => ({ ...prev, unsavedChanges: [...prev.unsavedChanges, customField] })); } };y el jsx:
<div className="App"> <input value={generalState.customField1} onChange={(e) => { changeTheState( "customField1", e.target.value, "field1", "customField1" ); }} /> <input value={generalState.customField2} onChange={(e) => { changeTheState( "customField2", e.target.value, "field2", "customField2" ); }} /> <h1>{generalState.unsavedChanges.length} # of unsaved changes.</h1> <button disabled={generalState.unsavedChanges.length > 0 ? false : true}> Submit </button> </div>aquí está el ejemplo: ejemplo de codesandbox
Una cosa más que puede hacer es crear un componente reutilizable para la entrada. crear una matriz de objetos para representar cada entrada. recorra la matriz y genere tantas entradas como desee.
si necesita una explicación adicional, hágamelo saber.