Reactjs 无法分配从useState内部的api检索到的值
当输入字段的值发生更改时,我想更新firmDetail的值。为此,我从API获取数据,并尝试将从API检索到的值分配给useState中的firmDetail。但由于从API检索数据的延迟,导致firmProfile中出现空值问题。这是我的密码:Reactjs 无法分配从useState内部的api检索到的值,reactjs,api,react-hooks,use-effect,use-state,Reactjs,Api,React Hooks,Use Effect,Use State,当输入字段的值发生更改时,我想更新firmDetail的值。为此,我从API获取数据,并尝试将从API检索到的值分配给useState中的firmDetail。但由于从API检索数据的延迟,导致firmProfile中出现空值问题。这是我的密码: const UseApiFetch = (url) => { const[data, setData]= useState(null); const[isPending, setPending]= useState(true);
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>
const UseApiFetch=(url)=>{
const[data,setData]=useState(null);
const[isPending,setPending]=useState(true);
const[error,setError]=useState(null);
useffect(异步()=>{
等待axios.get(url),然后(
响应=>{
如果(!response.status==“200”){
抛出错误(“获取数据时出错”);
}
setData(response.data);
setPending(假);
console.log(response.data);
})
.catch((错误=>{
setPending(假);
setError(error.message);
})
)
},[url]);
返回{data,isPending,error}
}
const{data:firmProfile,isPending,error}=UseApiFetch(constants.FIRM_PROFILE_URI);
const[firmDetail,setFirmDetail]=useState({
公司名称:“,
电邮:「,
固定电话:“,
firmUrl:“”,
更新日期:“,
名字:“
})
useffect(()=>{
固定细节({
…非常详细,
firmName:firmProfile.firmSubscriptionDetail.firmName,
firmEmail:firmProfile.firmSubscriptionDetail.ltbDecisionEmail,
firmPhone:firmProfile.firmSubscriptionDetail.ltbDecisionPhone,
firmUrl:firmProfile.firmSubscriptionDetail.firmUrl,
更新日期: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;
// }
功能手柄更改(evt){
常量值=evt.target.value;
固定细节({
…非常详细,
[evt.target.name]:值
});
}
返回(
{error&&{error}
{iSping&&
}
{firmProfile&&
坚定的
轮廓
公司名称:
handleChange(e)}/>
联络电邮:
handleChange(e)}/>
联络电话:
handleChange(e)}/>
固定网址:
handleChange(e)}/>
购买日期:
handleChange(e)}/>
案例重命名
handleChange(e)}/>
更新
}
firmDetail
不能是无条件调用setFirmDetail
的效果的依赖项,因为这将创建一个渲染循环。我怀疑您是想使用UseApiFetch
钩子中的firmProfile
数据响应
useffect
钩子将在初始渲染周期运行,很可能在GET请求解析之前运行。在尝试访问嵌套属性之前,您应该通过检查可能为null的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而不是firmProfile。这两种用法不都一样吗?@Sujan这主要是基于上下文的预感。你没有在任何地方使用firmDetail
状态,但你是根据最初从firmProfile
收到的值来更新它的。尽管现在我在看y我们的代码您似乎通过使用defaultValue
属性和onChange
处理程序混合了部分受控和非受控输入。如果您想要完全受控的输入,那么您应该使用value
属性,如果您想要完全非受控的输入,那么您应该使用defaultValue
并等待渲染r输入,直到填充了firmProfile
。感谢您的支持help@Sujan非常欢迎!如果此答案有助于解决您的问题,那么我邀请您将其标记为已接受。干杯,祝您好运。