如何按顺序使用 useEffect 运行?
How do I make useEffect run in order?
我的目标是获取我的 API 并在组件安装时对数据进行一些逻辑处理。当第一次提取调用成功时,我创建了另一个仅 运行 的 useEffect。我能够获取所有数据,但出现错误 "cannot read property 'length' of null"。如果我理解正确,第二个 useEffect 将在 companyData 更改时 运行。
错误:
54 | useEffect(() => {
55 | async function organizeReviews() {
56 | let companyReviews = []
> 57 | for(let i = 0; i < companyData.length; i++) {
| ^ 58 | let reviewsForThisCo = []
59 | // loop through userReviews array
60 | for(let j=0; j < userReviews.length; j++) {
代码:
const [averageRatings, setAverageRatings] = useState(null)
const [companyData, setCompanyData] = useState(null)
const [userReviews, setUserReviews] = useState([])
const [organizedReviews, setOrganizedReviews] = useState(null)
// Adding empty [] as second argument to run once component mounts
useEffect(() => {
async function getRatings() {
try{
const ratingRes = await fetch(process.env.REACT_APP_API_URL + '/api/v1/collected_reviews/')
const ratingJson = await ratingRes.json()
setAverageRatings(ratingJson.data)
} catch(err) {
console.log(err);
}
}
async function getCompanyData() {
try{
const companyDataRes = await fetch(process.env.REACT_APP_API_URL + '/api/v1/companies/')
const companyDataJson = await companyDataRes.json()
setCompanyData(companyDataJson.data)
} catch(err) {
console.log(err);
}
}
async function getCompanyReviews() {
try{
const reviewsRes = await fetch(process.env.REACT_APP_API_URL + '/api/v1/reviews/')
const reviewsJson = await reviewsRes.json()
setUserReviews(reviewsJson.data)
} catch(err) {
console.log(err);
}
}
getRatings()
getCompanyData()
getCompanyReviews()
}, [])
useEffect(() => {
async function organizeReviews() {
let companyReviews = []
for(let i = 0; i < companyData.length; i++) {
let reviewsForThisCo = []
// loop through userReviews array
for(let j=0; j < userReviews.length; j++) {
// if the user review id matches the company id
if(userReviews[j].company.id === companyData[i].id) {
reviewsForThisCo.push(userReviews[j])
}
}
companyReviews.push(reviewsForThisCo)
}
setOrganizedReviews(companyReviews)
}
organizeReviews()
}, [companyData])
the second useEffect will run whenever companyData changes.
没错。但它也总是 运行 在组件的初始安装上。所以你必须确保你的 companyData
存在于你的第二个 useEffect
中,因为它不会在第一次渲染时存在:
useEffect(() => {
if (companyData){
async function organizeReviews() {
let companyReviews = []
for(let i = 0; i < companyData.length; i++) {
let reviewsForThisCo = []
// loop through userReviews array
for(let j=0; j < userReviews.length; j++) {
// if the user review id matches the company id
if(userReviews[j].company.id === companyData[i].id) {
reviewsForThisCo.push(userReviews[j])
}
}
companyReviews.push(reviewsForThisCo)
}
setOrganizedReviews(companyReviews)
}
organizeReviews()
} // if (companyData)
}, [companyData])
现在它会在第一次渲染时 运行,但什么都不做,因为 companyData
还不存在。然后它会 运行 每次 companyData
改变。
请在第二个 useEffect 中使用 useRef(),如下所示
const mounted = useRef();
useEffect(() => {
if (!mounted.current) {
mounted.current = true;
} else {
async function organizeReviews() {
let companyReviews = []
for(let i = 0; i < companyData.length; i++) {
let reviewsForThisCo = []
// loop through userReviews array
for(let j=0; j < userReviews.length; j++) {
// if the user review id matches the company id
if(userReviews[j].company.id === companyData[i].id) {
reviewsForThisCo.push(userReviews[j])
}
}
companyReviews.push(reviewsForThisCo)
}
setOrganizedReviews(companyReviews)
}
organizeReviews()
}
}, [companyData])
If I understood correctly, the second useEffect will run whenever companyData changes.
是的,但是当第二个 useEffect 尝试将 .length 应用于 "companyData" 时,它仍然为空,并且您不能将 .length 应用于空变量。此错误在 "companyData" 更改
之前停止执行
你要做的就是将"companyData"初始化为一个空数组
const [companyData, setCompanyData] = useState([])
这是比较简单的方法,或者你可以复习里面第二个useEffect是"companyData"存在
useEffect(() => {
async function organizeReviews() {
let companyReviews = []
for(let i = 0; i < companyData.length; i++) {
let reviewsForThisCo = []
// loop through userReviews array
for(let j=0; j < userReviews.length; j++) {
// if the user review id matches the company id
if(userReviews[j].company.id === companyData[i].id) {
reviewsForThisCo.push(userReviews[j])
}
}
companyReviews.push(reviewsForThisCo)
}
setOrganizedReviews(companyReviews)
}
if (companyData)
organizeReviews()
}, [companyData])
我的目标是获取我的 API 并在组件安装时对数据进行一些逻辑处理。当第一次提取调用成功时,我创建了另一个仅 运行 的 useEffect。我能够获取所有数据,但出现错误 "cannot read property 'length' of null"。如果我理解正确,第二个 useEffect 将在 companyData 更改时 运行。
错误:
54 | useEffect(() => {
55 | async function organizeReviews() {
56 | let companyReviews = []
> 57 | for(let i = 0; i < companyData.length; i++) {
| ^ 58 | let reviewsForThisCo = []
59 | // loop through userReviews array
60 | for(let j=0; j < userReviews.length; j++) {
代码:
const [averageRatings, setAverageRatings] = useState(null)
const [companyData, setCompanyData] = useState(null)
const [userReviews, setUserReviews] = useState([])
const [organizedReviews, setOrganizedReviews] = useState(null)
// Adding empty [] as second argument to run once component mounts
useEffect(() => {
async function getRatings() {
try{
const ratingRes = await fetch(process.env.REACT_APP_API_URL + '/api/v1/collected_reviews/')
const ratingJson = await ratingRes.json()
setAverageRatings(ratingJson.data)
} catch(err) {
console.log(err);
}
}
async function getCompanyData() {
try{
const companyDataRes = await fetch(process.env.REACT_APP_API_URL + '/api/v1/companies/')
const companyDataJson = await companyDataRes.json()
setCompanyData(companyDataJson.data)
} catch(err) {
console.log(err);
}
}
async function getCompanyReviews() {
try{
const reviewsRes = await fetch(process.env.REACT_APP_API_URL + '/api/v1/reviews/')
const reviewsJson = await reviewsRes.json()
setUserReviews(reviewsJson.data)
} catch(err) {
console.log(err);
}
}
getRatings()
getCompanyData()
getCompanyReviews()
}, [])
useEffect(() => {
async function organizeReviews() {
let companyReviews = []
for(let i = 0; i < companyData.length; i++) {
let reviewsForThisCo = []
// loop through userReviews array
for(let j=0; j < userReviews.length; j++) {
// if the user review id matches the company id
if(userReviews[j].company.id === companyData[i].id) {
reviewsForThisCo.push(userReviews[j])
}
}
companyReviews.push(reviewsForThisCo)
}
setOrganizedReviews(companyReviews)
}
organizeReviews()
}, [companyData])
the second useEffect will run whenever companyData changes.
没错。但它也总是 运行 在组件的初始安装上。所以你必须确保你的 companyData
存在于你的第二个 useEffect
中,因为它不会在第一次渲染时存在:
useEffect(() => {
if (companyData){
async function organizeReviews() {
let companyReviews = []
for(let i = 0; i < companyData.length; i++) {
let reviewsForThisCo = []
// loop through userReviews array
for(let j=0; j < userReviews.length; j++) {
// if the user review id matches the company id
if(userReviews[j].company.id === companyData[i].id) {
reviewsForThisCo.push(userReviews[j])
}
}
companyReviews.push(reviewsForThisCo)
}
setOrganizedReviews(companyReviews)
}
organizeReviews()
} // if (companyData)
}, [companyData])
现在它会在第一次渲染时 运行,但什么都不做,因为 companyData
还不存在。然后它会 运行 每次 companyData
改变。
请在第二个 useEffect 中使用 useRef(),如下所示
const mounted = useRef();
useEffect(() => {
if (!mounted.current) {
mounted.current = true;
} else {
async function organizeReviews() {
let companyReviews = []
for(let i = 0; i < companyData.length; i++) {
let reviewsForThisCo = []
// loop through userReviews array
for(let j=0; j < userReviews.length; j++) {
// if the user review id matches the company id
if(userReviews[j].company.id === companyData[i].id) {
reviewsForThisCo.push(userReviews[j])
}
}
companyReviews.push(reviewsForThisCo)
}
setOrganizedReviews(companyReviews)
}
organizeReviews()
}
}, [companyData])
If I understood correctly, the second useEffect will run whenever companyData changes.
是的,但是当第二个 useEffect 尝试将 .length 应用于 "companyData" 时,它仍然为空,并且您不能将 .length 应用于空变量。此错误在 "companyData" 更改
之前停止执行你要做的就是将"companyData"初始化为一个空数组
const [companyData, setCompanyData] = useState([])
这是比较简单的方法,或者你可以复习里面第二个useEffect是"companyData"存在
useEffect(() => {
async function organizeReviews() {
let companyReviews = []
for(let i = 0; i < companyData.length; i++) {
let reviewsForThisCo = []
// loop through userReviews array
for(let j=0; j < userReviews.length; j++) {
// if the user review id matches the company id
if(userReviews[j].company.id === companyData[i].id) {
reviewsForThisCo.push(userReviews[j])
}
}
companyReviews.push(reviewsForThisCo)
}
setOrganizedReviews(companyReviews)
}
if (companyData)
organizeReviews()
}, [companyData])