Как уже упоминалось @Titus, это потому, что { method: 'GET' }
референциально отличается при каждом новом рендере.Но я считаю, что удаление этого компонента недостаточно гибко в реальной жизни.Необходимость передачи токена в заголовки или любое другое динамическое вычисление является довольно ожидаемым требованием, верно?
Вариант 1. Мы можем использовать JSON.stringify
для передачи объекта параметра в виде строки:
function useMyFetch(url, options) {
useEffect(() => {
}, [url, JSON.stringify(options)])
}
Вариант 2. Мы можем использовать useRef
до для сохранения предыдущих реквизитов и использовать пользовательское сравнение:
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
обычнопусто (без дополнительных заголовков).