[英]How to return a function from React Hooks that need access to the state?
我正在構建一個自定義鈎子來管理來自 fetch/axios/promise/whateveryouwant function 的數據,這個鈎子允許我隨時使用我在鈎子末尾返回的更新 function 更新數據。
所以現在我的鈎子中有兩個狀態:
const [data, setData] = useState<T>(defaultValue); // the data coming from the fetch, T is defined by the user of the hook
const [query, setQuery] = useState<Array<{ key: string; value: string }>>([]); // array of query option for the URL
I wanted to implement a dynamic way to add query string to the URL, so I used the query state to have an array of object representing what I wanted but I cannot access the value of the query inside of the update function when calling from outside. 這是鈎子,我強調了重要的部分:
export default function useFetchV2<T>(
defaultValue: T,
getData: (queryString?: string) => Promise<T>
): {
update: () => void;
data: T;
updateQueryValue: (key: string, value: string) => void; // update, data, updateQueryValue are the return value of the hook.
} {
const [data, setData] = useState<T>(defaultValue);
const [query, setQuery] = useState<Array<{ key: string; value: string }>>([]); // THE STATE I WANT TO ACCESS
console.log(query, data); // Here the state is updating well and everything seems fine
const update = useCallback((): void => {
let queryString;
console.log(query, data);
// But here is the problem, query and data are both at their default value. The state inside the hooks is correct but not here.
if (query.length > 0) { // query.length always at 0
queryString = _.reduce(
query,
(acc, el) => {
return `${acc}${el.key}=${el.value.toString()}`;
},
'?'
);
console.log(queryString);
}
getData(queryString).then(res => setData(res));
}, [data, getData, query]);
const updateQueryValue = useCallback(
(key: string, value: string): void => {
const index = query.findIndex(el => el.key === key);
if (index !== -1) {
if (!value) {
const toto = [...query];
_.pullAt(toto, index);
setQuery(toto);
} else {
setQuery(prev =>
prev.map(el => {
if (el.key === key) {
return { key, value };
}
return el;
})
);
}
} else {
console.log(key, value); // everything is logging well here, good key and value
setQuery([...query, { key, value }]); // setQuery correctly update the state
}
update();
},
[query, update]
);
useEffect(() => {
update();
}, []);
return { update, data, updateQueryValue };
}
這可能是我導出function的方式,我仍然不習慣scope。
我從一個組件中調用了 updateQueryValue。 調用了function,改了state,但是更新function看不出區別。
代碼調用setQuery
然后立即調用update
並期望query
是更新的值,但它始終是query
的當前值。 實現這一點是useEffect
的用例。
} else {
console.log(key, value); // everything is logging well here, good key and value
setQuery([...query, { key, value }]); // setQuery correctly update the state
}
// This will *always* see the current value of `query`, not the one that
// was just created in the `else` block above.
update();
query
update
,這正是useEffect
的用途。const updateQueryValue = useCallback(
(key: string, value: string): void => {
const index = query.findIndex(el => el.key === key);
if (index !== -1) {
if (!value) {
const toto = [...query];
_.pullAt(toto, index);
setQuery(toto);
} else {
setQuery(prev =>
prev.map(el => {
if (el.key === key) {
return { key, value };
}
return el;
})
);
}
} else {
setQuery([...query, { key, value }]); // setQuery correctly update the state
}
// This call isn't needed, it will always "see" the old value of
// `query`
// update();
},
[query, update]
);
// Call `update` once when this custom hook is first called as well as
// whenever `query` changes.
useEffect(() => {
update();
}, [query]); // <-- this is new, add `query` as a dependency
useCallback
僅在依賴 function 的身份做出決定時才需要; 例如,如果一個組件接收到 function 作為 prop,它會檢查 prop 是否發生變化以決定是否重新渲染。 在這種情況下update
不需要useCallback
並且可能會使這個鈎子更難調試。function update() {
let queryString;
if (query.length > 0) { // query.length always at 0
queryString = _.reduce(
query,
(acc, el) => {
return `${acc}${el.key}=${el.value.toString()}`;
},
'?'
);
console.log(queryString);
}
getData(queryString).then(res => setData(res));
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.