无法分配从useState内的api检索到的值



当输入字段的值发生变化时,我想更新firmDetail的值。为此,我从API获取数据,并尝试将从API检索到的值分配给useState中的firmDetail。但由于从API检索数据的延迟导致了firmProfile中的空值问题。这是我的代码:

const UseApiFetch = (url) => {
const[data, setData]= useState(null);
const[isPending, setPending]= useState(true);
const[error, setError]= useState(null);
useEffect( async ()=>{
await axios.get(url).then(
response =>{
if(!response.status=== "200"){
throw error('error while fetching data');
}
setData(response.data);
setPending(false);
console.log(response.data);
})
.catch((error => {
setPending(false);
setError(error.message);
})
)
}, [url]);
return{data, isPending, error}
}
const { data: firmProfile, isPending, error } = UseApiFetch(constants.FIRM_PROFILE_URI);
const[firmDetail, setFirmDetail]= useState({
firmName:"",
firmEmail:"",
firmPhone:"",
firmUrl:"",
pDate:"",
cRename:""
})
useEffect(()=>{
setFirmDetail({
...firmDetail,
firmName: firmProfile.firmSubscriptionDetail.firmName,
firmEmail: firmProfile.firmSubscriptionDetail.ltbDecisionEmail,
firmPhone: firmProfile.firmSubscriptionDetail.ltbDecisionPhone,
firmUrl: firmProfile.firmSubscriptionDetail.firmURL,
pDate: firmProfile.firmSubscriptionDetail.purchaseDate,
cRename: firmProfile.firmSubscriptionDetail.caseRename
})
}, [firmDetail])
// if(firmProfile){
//     firmDetail.firmName = firmProfile.firmSubscriptionDetail.firmName;
//     firmDetail.firmEmail=firmProfile.firmSubscriptionDetail.ltbDecisionEmail;
//     firmDetail.firmPhone=firmProfile.firmSubscriptionDetail.ltbDecisionPhone;
//     firmDetail.firmUrl=firmProfile.firmSubscriptionDetail.firmURL;
//     firmDetail.pDate=firmProfile.firmSubscriptionDetail.purchaseDate;
//     firmDetail.cRename=firmProfile.firmSubscriptionDetail.caseRename;
// }
function handleChange(evt) {
const value = evt.target.value;
setFirmDetail({
...firmDetail,
[evt.target.name]: value
});
}
return (
<div className="content">
{error && <div>{error}</div>}
{isPending &&
<div><Loader /></div>
}
<div className="firmDetail">
{ firmProfile &&
<div className="col-lg-6">
<CCard>
<CCardHeader>
Firm
<small> Profile</small>
</CCardHeader>
<CCardBody>
<CFormGroup>
<CLabel htmlFor="name">Firm Name:</CLabel>
<CInput id="firmName" name="firmName" defaultValue={firmProfile.firmSubscriptionDetail.firmName} onChange={(e)=>handleChange(e)}/>
</CFormGroup>
<CFormGroup>
<CLabel htmlFor="email">Contact Email:</CLabel>
<CInput id="firmEmail" name="firmEmail" type="email" defaultValue={firmProfile.firmSubscriptionDetail.ltbDecisionEmail} onChange={(e)=>handleChange(e)}/>
</CFormGroup>
<CFormGroup>
<CLabel htmlFor="phone">Contact Phone:</CLabel>
<CInput id="firmPhone" name="firmPhone"  defaultValue={firmProfile.firmSubscriptionDetail.ltbDecisionPhone} onChange={(e)=>handleChange(e)}/>
</CFormGroup>
<CFormGroup>
<CLabel htmlFor="">Firm Url:</CLabel>
<CInput id="firmUrl" name="firmUrl" defaultValue={firmProfile.firmSubscriptionDetail.firmURL} onChange={(e)=>handleChange(e)}/>
</CFormGroup>
<CFormGroup>
<CLabel htmlFor="date">Purchase Date:</CLabel>
<CInput id="date" name="pDate" defaultValue={firmProfile.firmSubscriptionDetail.purchaseDate} onChange={(e)=>handleChange(e)}/>
</CFormGroup>
<CFormGroup>
<CLabel htmlFor="case">Case Rename</CLabel>
<CInput id="caseRename" name="cRename" defaultValue={firmProfile.firmSubscriptionDetail.caseRename} onChange={(e)=>handleChange(e)}/>
</CFormGroup>
<Row className="float-right">
<Button variant="success pull-right" className="float-right">Update</Button>
</Row>
</CCardBody>
</CCard>
</div>
}
</div>

firmDetail不能是无条件调用setFirmDetail的效果的依赖项,因为这将创建渲染循环。我怀疑您的意思是使用来自UseApiFetch挂钩的firmProfile数据响应。

useEffect钩子将在最初的渲染周期中运行,可能早在GET请求解析之前。在尝试访问嵌套属性之前,您应该通过检查firmProfile值是否存在来说明可能为空的值。只有当它是truthy/defined时,才应该实际将状态更新排入队列。

useEffect(()=>{
firmProfile && setFirmDetail({
firmName: firmProfile.firmSubscriptionDetail.firmName,
firmEmail: firmProfile.firmSubscriptionDetail.ltbDecisionEmail,
firmPhone: firmProfile.firmSubscriptionDetail.ltbDecisionPhone,
firmUrl: firmProfile.firmSubscriptionDetail.firmURL,
pDate: firmProfile.firmSubscriptionDetail.purchaseDate,
cRename: firmProfile.firmSubscriptionDetail.caseRename,
})
}, [firmProfile]);

从JSX 中的firmDetail状态渲染

{!isPending &&
<div className="col-lg-6">
<CCard>
<CCardHeader>
Firm
<small> Profile</small>
</CCardHeader>
<CCardBody>
<CFormGroup>
<CLabel htmlFor="name">Firm Name:</CLabel>
<CInput
id="firmName"
name="firmName"
value={firmDetail.firmName} // <-- controlled input
onChange={handleChange}
/>
</CFormGroup>
...

最新更新