无法分配从 useState 中的 api 检索到的值
Cannot assign value retrieved from api inside useState
我想在输入字段的值发生变化时更新 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>
...
我想在输入字段的值发生变化时更新 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>
...