这是我的代码:
const useMyFetch = (url, options) =>
{
const [response, setResponse] = React.useState(null);
React.useEffect(() =>
{
console.log("going to fetch ", url);
fetch(url, options).then(async function(response)
{
var json = await response.json();
setResponse(json.message);
});
}, [ url ]);
return response;
};
function Example()
{
const res = useMyFetch("https://dog.ceo/api/breeds/image/random", { method: 'GET' });
if (!res)
{
return <div>loading...</div>
}
return <img src={res} alt="an image" />;
}
看起来一切都很好...除了当我将useEffect的第二个参数从[url]替换为[url,options]时。 当存在“选项”时,我们将进入众所周知的无限循环……但是将其包含在此数组中是合乎逻辑的。怎么了 谢谢
答案 0 :(得分:1)
将{ method: 'GET' }
定义为常量对象,以使options
参数始终相同,这是一个示例:
const options = { method: 'GET' };
function Example() {
const res = useMyFetch("https://dog.ceo/api/breeds/image/random", options);
...
}
否则,由于options
为useMyFetch
,因此每次调用{ method: 'GET' } === { method: 'GET' }
时,false
将被视为已更改。
答案 1 :(得分:0)
查找要测试的网址show the image 它应该返回setResponse您想要的内容
const useMyFetch = (url, options) =>
{
const [response, setResponse] = React.useState(null);
React.useEffect(() =>
{
console.log("going to fetch ", url);
fetch(url, options).then(async (response)=>
{
var json = await response.json();
return setResponse(json.message);
});
}, [ url ]);
return response;
};
function Example()
{
const res = useMyFetch("https://dog.ceo/api/breeds/image/random", { method: 'GET' });
if (!res)
{
return <div>loading...</div>
}
return <img src={res} alt="an image" />;
}
export default Example;
答案 2 :(得分:0)
正如@Titus所提到的,这是因为{ method: 'GET' }
在每个新渲染中都存在参考差异。但是我相信,将组件移出现实生活中不够灵活。需要将令牌传递到标头或其他任何动态计算是预期的要求,对吧?
选项1。我们可以使用JSON.stringify
将参数对象作为字符串传递:
function useMyFetch(url, options) {
useEffect(() => {
}, [url, JSON.stringify(options)])
}
选项2。我们可以使用useRef
至store previous props并使用自定义比较:
function useMyFetch(url, options) {
const prevOptions = useRef(null);
useEffect(() => {
...
prevOptions.current = options;
}, [url, customCompare(options, prevOptions.current)])
}
选项3。最后,我可以创建自定义钩子,如果所有嵌套属性均相等,则该钩子将返回引用相同的对象:
function useObject(obj) {
const prevObj = useRef(obj);
const isEqual = _.isEqual(prevObj.current, obj);
useEffect(() => {
prevObj.current = obj;
}, [isEqual]);
return isEqual ? prevObj.current : obj;
}
,以后用作
function Example()
{
const requestOptions = useObject({ method: 'GET' });
const res = useMyFetch("https://dog.ceo/api/breeds/image/random", requestOptions);
if (!res)
{
return <div>loading...</div>
}
return <img src={res} alt="an image" />;
}
选项4。最直接的方法是将对象options
分解为原始值:
function useMyFetch(url, options) {
const {method, headers: {contentType} = {} , ...rest } = options;
useEffect(() => {
}, [url, method, contentType, JSON.stringify(rest)]);
}
我相信虽然此方法比上面的方法更为详尽,但它会更快一些,特别是如果rest
通常为空(没有多余的标头)。