React Native - 仅在状态发生变化时获取输入值
我有一个非常简单的表单,包含两个元素。一个是 TextInput
,另一个是 DateTimePicker
。我通过点击 TouchableHighlight
列表中的一个元素来调用此表单。点击后,我发送我点击的元素的索引,并使用它从数组中获取对象。
当我打开包含输入和日期时间的编辑表单时,编辑其中任何一个并点击确认我的代码工作正常。
但是,如果在关闭此字段后,打开另一个字段并仅编辑两个字段之一,则另一个(未修改的)字段将采用状态变量中最后保存的值。这个值是之前修改的值,因为由于我没有更新这个字段,所以它的变量的状态值没有改变。
我的问题是如何避免这种情况?我怎样才能检测到哪个字段发生了变化并让其他字段保持不变。我可以创建一个状态变量,仅当字段值更改时该变量才会更改。这不是我正在寻找的解决方案,因为如果我有 100 个字段怎么办?
在我的代码下面:
//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>
)
这是
的代码
<DateTimePicker
mode="time"
display="default"
style={styles.androidTimePicker}
is24Hour={is24h()}
value={programTimeToDate}
onChange={updateTime}/>
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}/>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论