Fetch API 请求后需要同步更新状态
Need to Update State Synchronously after Fetch API Request
我有一个搜索组件,它从 JSON 文件(目前是本地文件,但将来会是远程文件)中获取单个配置文件,并在输入字段下方显示匹配配置文件的信息。
目前,在我第一次提交搜索查询时,我发现我所有的状态变量 return 都未定义,因为如果我理解正确的话,状态在完整的承诺链完成之前不会更新解决。只有在我第二次提交搜索查询时,我的状态变量 return 才是过滤搜索结果的正确数据。
在第一次提交时,似乎正在初始化一个空数组,因为我的 {props.activeChart && `OPENED CHART : ${props.firstName} ${props.lastName} (DOB: ${props.DOB})`}
条件渲染变得真实,并渲染出 firstName、lastName 和 DOB 的空值。
编辑:我最近遇到了这个 post (),它似乎解决了异步获取和设置状态导致的相同问题,但 axios 除外。我已经尝试相应地修改我的代码(在下面编辑),但是在我的获取结果解决后我仍然无法更新状态。任何意见,将不胜感激。谢谢
import { useState } from 'react';
import StyledSearchForm from './SearchForm.styled';
const SearchForm = props => {
const [queryFirstName, setQueryFirstName] = useState('');
const [queryLastName, setQueryLastName] = useState('');
const [queryDOB, setQueryDOB] = useState('');
const handleQuery = async (e) => {
e.preventDefault();
const result = await fetchRecord();
console.log(result[0]) // fetched object successfully logged
if (result[0]) {
setActiveChart(result[0]);
console.log(activeChart) // activeChart still undefined
setFirstName(activeChart.firstName);
setLastName(activeChart.lastName);
setDOB(activeChart.dob);
}
};
const fetchRecord = () => (
fetch('http://localhost:8000/patients')
.then(resp => { return resp.json(); })
.then(data => {
const result = data.filter(patient => (
(patient.dob === queryDOB.trim() &&
patient.lastName.toLowerCase() ===
queryLastName.toLowerCase().trim()) ||
(patient.lastName.toLowerCase() ===
queryLastName.toLowerCase().trim() &&
patient.firstName.toLowerCase() ===
queryFirstName.toLowerCase().trim())
));
return {...result};
})
);
return (
<StyledSearchForm>
<form onSubmit={handleQuery}>
<label className="first-name" htmlFor="first-name">
First Name:
</label>
<input
type="text"
id="first-name"
className="form-fields"
name="fname"
value={queryFirstName}
onChange={e => setQueryFirstName(e.target.value)}
/>
<label className="last-name" htmlFor="last-name">
Last Name:
</label>
<input
type="text"
id="last-name"
className="form-fields"
name="lname"
value={queryLastName}
onChange={e => setQueryLastName(e.target.value)}
/>
<label className="dob" htmlFor="dob">
DOB:
</label>
<input
type="text"
id="dob"
className="form-fields"
name="dob"
value={queryDOB}
onChange={e => setQueryDOB(e.target.value)}
/>
<button className="submit-btn" type="submit" onClick={e => handleQuery}>Open Chart</button>
</form>
<div className="active-patient">
{props.activeChart && `OPENED CHART : ${props.firstName} ${props.lastName} (DOB: ${props.DOB})`}
</div>
</StyledSearchForm>
);
};
export default SearchForm;
看起来您希望 data
过滤器return 一个对象,但 Array.prototype.filter
(docs) return 是一个数组。数组,即使是空的,也是真实的。
您需要在此链中处理数组,而不是对象:
const fetchRecord = () =>
fetch("http://localhost:8000/patients")
.then((resp) => {
return resp.json();
})
.then((data) => {
// results is an array!
const results = data.filter(...);
if (results.length === 0) {
// no match - do something about it?
return {};
} else {
// return the first result?
return results[0];
}
})
.then((record) => {
props.setActiveChart(...record);
})
.then(() => {
props.setFirstName(props.activeChart.firstName);
props.setLastName(props.activeChart.lastName);
props.setDOB(props.activeChart.dob);
});
问题似乎是由于尝试在获取我的搜索结果的同一个异步函数中设置我的所有状态变量,以及在离开时将 if(results[0]) 语句移出 handleQuery 函数造成的只是 handleQuery 函数中的 setActiveChart() 解决了我的问题。
我有一个搜索组件,它从 JSON 文件(目前是本地文件,但将来会是远程文件)中获取单个配置文件,并在输入字段下方显示匹配配置文件的信息。
目前,在我第一次提交搜索查询时,我发现我所有的状态变量 return 都未定义,因为如果我理解正确的话,状态在完整的承诺链完成之前不会更新解决。只有在我第二次提交搜索查询时,我的状态变量 return 才是过滤搜索结果的正确数据。
在第一次提交时,似乎正在初始化一个空数组,因为我的 {props.activeChart && `OPENED CHART : ${props.firstName} ${props.lastName} (DOB: ${props.DOB})`}
条件渲染变得真实,并渲染出 firstName、lastName 和 DOB 的空值。
编辑:我最近遇到了这个 post (
import { useState } from 'react';
import StyledSearchForm from './SearchForm.styled';
const SearchForm = props => {
const [queryFirstName, setQueryFirstName] = useState('');
const [queryLastName, setQueryLastName] = useState('');
const [queryDOB, setQueryDOB] = useState('');
const handleQuery = async (e) => {
e.preventDefault();
const result = await fetchRecord();
console.log(result[0]) // fetched object successfully logged
if (result[0]) {
setActiveChart(result[0]);
console.log(activeChart) // activeChart still undefined
setFirstName(activeChart.firstName);
setLastName(activeChart.lastName);
setDOB(activeChart.dob);
}
};
const fetchRecord = () => (
fetch('http://localhost:8000/patients')
.then(resp => { return resp.json(); })
.then(data => {
const result = data.filter(patient => (
(patient.dob === queryDOB.trim() &&
patient.lastName.toLowerCase() ===
queryLastName.toLowerCase().trim()) ||
(patient.lastName.toLowerCase() ===
queryLastName.toLowerCase().trim() &&
patient.firstName.toLowerCase() ===
queryFirstName.toLowerCase().trim())
));
return {...result};
})
);
return (
<StyledSearchForm>
<form onSubmit={handleQuery}>
<label className="first-name" htmlFor="first-name">
First Name:
</label>
<input
type="text"
id="first-name"
className="form-fields"
name="fname"
value={queryFirstName}
onChange={e => setQueryFirstName(e.target.value)}
/>
<label className="last-name" htmlFor="last-name">
Last Name:
</label>
<input
type="text"
id="last-name"
className="form-fields"
name="lname"
value={queryLastName}
onChange={e => setQueryLastName(e.target.value)}
/>
<label className="dob" htmlFor="dob">
DOB:
</label>
<input
type="text"
id="dob"
className="form-fields"
name="dob"
value={queryDOB}
onChange={e => setQueryDOB(e.target.value)}
/>
<button className="submit-btn" type="submit" onClick={e => handleQuery}>Open Chart</button>
</form>
<div className="active-patient">
{props.activeChart && `OPENED CHART : ${props.firstName} ${props.lastName} (DOB: ${props.DOB})`}
</div>
</StyledSearchForm>
);
};
export default SearchForm;
看起来您希望 data
过滤器return 一个对象,但 Array.prototype.filter
(docs) return 是一个数组。数组,即使是空的,也是真实的。
您需要在此链中处理数组,而不是对象:
const fetchRecord = () =>
fetch("http://localhost:8000/patients")
.then((resp) => {
return resp.json();
})
.then((data) => {
// results is an array!
const results = data.filter(...);
if (results.length === 0) {
// no match - do something about it?
return {};
} else {
// return the first result?
return results[0];
}
})
.then((record) => {
props.setActiveChart(...record);
})
.then(() => {
props.setFirstName(props.activeChart.firstName);
props.setLastName(props.activeChart.lastName);
props.setDOB(props.activeChart.dob);
});
问题似乎是由于尝试在获取我的搜索结果的同一个异步函数中设置我的所有状态变量,以及在离开时将 if(results[0]) 语句移出 handleQuery 函数造成的只是 handleQuery 函数中的 setActiveChart() 解决了我的问题。