useEffect 导致死循环
useEffect causing infinite loop
我已经查看了 SO 中的每个无限循环答案,但我无法弄清楚我做错了什么。
我正在尝试获取一些数据并使用这些数据设置我的 productList 状态,但它会导致无限循环。
export default (props) => {
const [productsList, setProductsList] = useState([]);
const getProducts = async () => {
try {
await axios
.get("https://api.stripe.com/v1/skus", {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${StripeKey}`,
},
})
.then(({ data }) => {
setProductsList(data.data);
});
} catch {
(error) => {
console.log(error);
};
}
};
useEffect(() => {
getProducts();
}, [productList]);
return (
<ProductsContext.Provider value={{ products: productsList }}>
{props.children}
</ProductsContext.Provider>
);
};
我也试过在 useEffect 的末尾有一个空数组,这导致它根本不设置状态。
我错过了什么?
编辑:
我从 useEffect
中删除了 try/catch 和 [productList]
import React, { useState, useEffect } from "react";
import axios from "axios";
const StripeKey = "TEST_KEY";
export const ProductsContext = React.createContext({ products: [] });
export default (props) => {
const [productsList, setProductsList] = useState([]);
useEffect(() => {
axios({
method: "get",
url: "https://api.stripe.com/v1/skus",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${StripeKey}`,
},
})
.then((response) => {
setProductsList(response.data.data)
})
.catch((error) => {
console.log(error);
});
}, []);
return (
<ProductsContext.Provider value={{ products: productsList }}>
{props.children}
</ProductsContext.Provider>
);
};
关于您获取数据的方式:
我认为问题可能出在您获取数据的方式上:
如 docs 中所述,我认为您不应该在这里使用 try catch,而是像这样:
function MyComponent() {
const [error, setError] = useState(null);
const [isLoaded, setIsLoaded] = useState(false);
const [items, setItems] = useState([]);
// Note: the empty deps array [] means
// this useEffect will run once
// similar to componentDidMount()
useEffect(() => {
fetch("https://api.example.com/items")
.then(res => res.json())
.then(
(result) => {
setIsLoaded(true);
setItems(result.items);
},
// Note: it's important to handle errors here
// instead of a catch() block so that we don't swallow
// exceptions from actual bugs in components.
(error) => {
setIsLoaded(true);
setError(error);
}
)
}, [])
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<ul>
{items.map(item => (
<li key={item.name}>
{item.name} {item.price}
</li>
))}
</ul>
);
}
}
关于useEffect回调:
我认为您不应该使用 [productList] 作为您正在更新的项目,所以一旦您执行了 setProducts,它就会再次触发。当请求的道具发生变化或者只是在组件上挂载时,您可能想再次进行获取(如您所说的空数组)
此外,该代码示例可能还存在我们看不到的其他副作用。也许你可以分享一个 stackblitz 来确定
我已经查看了 SO 中的每个无限循环答案,但我无法弄清楚我做错了什么。
我正在尝试获取一些数据并使用这些数据设置我的 productList 状态,但它会导致无限循环。
export default (props) => {
const [productsList, setProductsList] = useState([]);
const getProducts = async () => {
try {
await axios
.get("https://api.stripe.com/v1/skus", {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${StripeKey}`,
},
})
.then(({ data }) => {
setProductsList(data.data);
});
} catch {
(error) => {
console.log(error);
};
}
};
useEffect(() => {
getProducts();
}, [productList]);
return (
<ProductsContext.Provider value={{ products: productsList }}>
{props.children}
</ProductsContext.Provider>
);
};
我也试过在 useEffect 的末尾有一个空数组,这导致它根本不设置状态。
我错过了什么?
编辑:
我从 useEffect
中删除了 try/catch 和 [productList]import React, { useState, useEffect } from "react";
import axios from "axios";
const StripeKey = "TEST_KEY";
export const ProductsContext = React.createContext({ products: [] });
export default (props) => {
const [productsList, setProductsList] = useState([]);
useEffect(() => {
axios({
method: "get",
url: "https://api.stripe.com/v1/skus",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${StripeKey}`,
},
})
.then((response) => {
setProductsList(response.data.data)
})
.catch((error) => {
console.log(error);
});
}, []);
return (
<ProductsContext.Provider value={{ products: productsList }}>
{props.children}
</ProductsContext.Provider>
);
};
关于您获取数据的方式: 我认为问题可能出在您获取数据的方式上:
如 docs 中所述,我认为您不应该在这里使用 try catch,而是像这样:
function MyComponent() {
const [error, setError] = useState(null);
const [isLoaded, setIsLoaded] = useState(false);
const [items, setItems] = useState([]);
// Note: the empty deps array [] means
// this useEffect will run once
// similar to componentDidMount()
useEffect(() => {
fetch("https://api.example.com/items")
.then(res => res.json())
.then(
(result) => {
setIsLoaded(true);
setItems(result.items);
},
// Note: it's important to handle errors here
// instead of a catch() block so that we don't swallow
// exceptions from actual bugs in components.
(error) => {
setIsLoaded(true);
setError(error);
}
)
}, [])
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<ul>
{items.map(item => (
<li key={item.name}>
{item.name} {item.price}
</li>
))}
</ul>
);
}
}
关于useEffect回调:
我认为您不应该使用 [productList] 作为您正在更新的项目,所以一旦您执行了 setProducts,它就会再次触发。当请求的道具发生变化或者只是在组件上挂载时,您可能想再次进行获取(如您所说的空数组)
此外,该代码示例可能还存在我们看不到的其他副作用。也许你可以分享一个 stackblitz 来确定