我正在从表单的三个独立填充的子部分中创建一个对象。它们是独立填充的,因为数据来自三个不同的来源:
1( 用于名称和地址的后端api2( 电话号码的第三方api3( 用户在表单中的其他字段上执行onChange
我注意到,如果我提交的表单中onChange是最后一个执行的函数,即如果输入备注或更新电子邮件地址,那么其他两个元素会删除一些数据,特别是每个源的第一个字段。
我已经通过创建一个基本上运行表单控制操作(基本上重置电话号码(的效果来解决这个问题,但很明显,我不想不依赖useState方法,并称它为某种东西,而不是为了解决我不理解的问题。这是一些代码。
谢谢!
const leadContext = useContext(LeadContext);
const { clearLiens, lien, setLien, letCall, number, clearNumber, addLead, postLogics } = leadContext;
useEffect(() => {
if (lien !== null) {
setRecord(lien);
}else {
setRecord({
name: '',
address:'',
city:'',
state:'',
zip:'',
plaintiff:'',
amount:''
});
}
}, [lien, leadContext]);
useEffect (()=>{
if(number !== null){
setCall({phone:number});
}else {
setCall({phone:''});
}
},[number, leadContext]);
const [ record, setRecord ] = useState({
name: '',
address:'',
city:'',
state:'',
zip:'',
plaintiff:'',
amount:'',
lienid:''
});
const [ call, setCall ] = useState({
phone: ''});
const [ open, setOpen ] = useState({
email:'',
lexId:'',
compliant:'filed',
filingStatus:'married',
cpa: 'cpa',
ssn:'',
noteText:''
});
const onChange = e => {
setRecord({...name, address, city, state, zip, plaintiff, amount, [e.target.name]: e.target.value });
setCall({...phone, [e.target.name]: e.target.value });
setOpen({...email, lexId, compliant, filingStatus, cpa, ssn, noteText, [e.target.name]: e.target.value});
}
const { name, address, city, state, zip, plaintiff, amount, lienid } = record
const { phone } = call
const { email, lexId, compliant, filingStatus, cpa, ssn, noteText } = open
const lead = {phone, name, address, city, state, zip, plaintiff, amount, lienid, email, lexId, compliant, filingStatus, cpa, ssn, noteText }
const clearLead = () => {
clearNumber();
setLien('');
setRecord({
name: '',
address:'',
city:'',
state:'',
zip:'',
plaintiff:'',
amount:'',
});
setCall({
phone: ''});
setOpen({
email:'',
lexId:'',
compliant:'filed',
filingStatus:'m',
cpa: 'cpa',
noteText:'',
ssn:''
});
}
const onSubmit = e => {
e.preventDefault();
addLead(lead);
clearAll();
};
const clearAll = () => {
clearLiens();
clearLead();
};
const onClick = e => {
letCall(number);
}
letCall(number(是我的热门修复程序,基本上是在其中一个表单字段上调用set state。我也无法将其堆叠到提交时,所以它必须作为一个单独的函数来完成。
const addLead = async lead => {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const { phone, name, address, city, state, zip, plaintiff, amount, lienid, email, lexId, compliant, filingStatus, cpa, ssn, noteText } = lead
const noteId = uuidv4();
const notes = [{ id : noteId,
note : noteText,
notePostedBy: ''
}]
const steve = {phone, name, address, city, state, zip, plaintiff, amount, lienid, email, lexId, compliant, filingStatus, cpa, ssn, notes }
console.log(lead,'1');
console.log(steve,'1');
const res = await axios.post('/api/leads/', steve, config);
dispatch({
type: POST_LEAD,
payload: res.data
});
};
看起来这与在onChange
中更新状态值的方式有关。具体来说,你写:
setRecord({...name, address, city, state, zip, plaintiff, amount, [e.target.name]: e.target.value });
但是,由于name
不可扩展,它变为空值,因此更新的record
状态将不具有name
的值(除非name
是更改的输入(。
要解决此问题,您可以使用简化更新
const onChange = e => {
setRecord(prev => ({...prev, [e.target.name]: e.target.value}));
setCall(prev => ({...prev, [e.target.name]: e.target.value}));
setOpen(prev => ({...prev, [e.target.name]: e.target.value}));
}
但是,您可能还想添加某种检查来更新正确的状态对象,这样键就不会被放入所有状态对象中。类似于:
const onChange = e => {
if (Object.keys(record).includes(e.target.name) {
setRecord(prev => ({...prev, [e.target.name]: e.target.value}));
}
// and so on...
}
编辑:
当使用回调版本的set[State]
时,事件将变为null
,因为回调是异步调用的(特别是在其他时间(。要解决此问题,您可以使用:
e.persist();
在onChange
函数的顶部(然而在这种情况下可能不是最优的(。
或者从e.target
获取name
和value
,并将它们直接传递给回调。例如:
const onChange = e => {
const { name, value } = e.target;
if (Object.keys(record).includes(name) {
setRecord(prev => ({...prev, [name]: value}));
}
// and so on...
}
这可能是这里最合适的解决方案。