I have a very simple form with two elements. One is a TextInput, the other one a DateTimePicker. I call this form by tapping on one element in a list of TouchableHighlight. After tapping, I send the index of the element I tapped and use it to get the object from an array.
When I open the edit form containing an Input and a dateTime, edit any of them and tap confirm my code works fine.
However if after I close this one, I open another one and edit only one of both fields, the other (non-modified) field will take the last saved value in the state variable. This value is the value for the previous modification, because since I did not updated this field, the state value for it's variable hasn't changed.
My question is how to avoid this? How can I detect which field changed and let the other remain the same. I could create a state variable that will change only if the field value changes. That is not the solution I'm looking for because what if I have 100 fields?
Below my code:
//Here I get the element the user tapped.
const element = arrayOfElems[index]
/**
These are the current values of each element. I store them here instead of in a state,
because If I always use the state if the user makes no change, then the displayed
values are replaced for those stored in the state.
**/
const defaultName = element.name;
const defaultTime = element.time;
//A state variable to determine if any field has been modified
const [edit, setEdit] = useState(false)
//Set a state variable for the name and time values of the selected element
const [nameInState, setNameInState] = useState(defaultName)
const [timeInState, settimeInState] = useState(defaultTime)
/** My guess is my problem is here, because no matter which field
I modify, I set the edit state to true. It's the way I came up to
determine if the form had been modified. If I don't do this and
use the setState directly in the input, then if I save with no changes,
the values are changed to the previous saved state.**/
const updateValue = (value):string | number => {
setEdit(true)
if (typeof value == "number"){
settimeInState(value)
return timeInState
}
setNameInState(value)
return nameInState
}
/** If the user has made no changes, I save the default values
instead of those in the state variables. **/
const getValue = (type) => {
if(type === "time"){
return edit ? timeInState : defaultTime
}
return edit ? nameInState : defaultName
}
// This is the action when the user taps confirm
const updateInfoInDb = ():void => {
if (typeof timeInState !== "number") { return }
appoint.editSched(index, personId, {
name: getValue("name"),
time: getValue("time"),
} as IAppointm)
.then(() => {
doStuff()
})
.catch((err) => {
setLoading(false)
})
setEdit(false)
}
return(
<View style={Modals.styles.modalBody}>
<Input
inputContainerStyle={Inputs.outlined}
defaultValue={defaultName}
onChangeText={updateValue}
errorStyle={Inputs.errorMessage}
/>
<Text style={Modals.styles.label} tx="en.modifyTimeDate" />
<TimePicker programTime={getValue("time")} updateTime={updateValue} />
<DefaultButton
action={updateInfoInDb}
disabled={disabled}
disabledStyle={"disabled"}
loading={loading}
size={"base"}
style={"primary"}
text={"common.confirm"}
/>
</View>
)
This is the code for the <TimePicker/>
<DateTimePicker
mode="time"
display="default"
style={styles.androidTimePicker}
is24Hour={is24h()}
value={programTimeToDate}
onChange={updateTime}/>