Vì sao dữ liệu trong state không được update
Mọi người giúp mình bài toán này với, mình đang làm thử chức năng load-more
sử dụng useReducer
và useEffect
của react-hooks
.
Link demo: https://codesandbox.io/s/load-more-pmr3t?file=/src/ScrollLoadMore.js:1258-1270
Lúc đầu, mình thực hiện handleFetchUsers
thành công và có set giá trị cho biến totalPages
ở trong reducer.
Nhưng khi ở hàm handleScroll
mình lấy biến totalPages
ra để check điều kiện thì nó lại không đúng với giá trị mà mình đã set trước đó trong reducer.
Mọi người có thể giải thích thêm giúp mình được không. Mình xin cám ơn các bạn !
5 CÂU TRẢ LỜI
Do đây là functional component nên hàm handleScroll sẽ có closure trên ScrollLoadMore (tức nó ghi nhớ giá trị của scope bên ngoài lúc đc khởi tạo => khi này state là init)
Vậy nên bạn cần attach/remove listener mỗi khi state thay đổi.
Đơn giản là tạo 1 hook nữa như sau (nhớ xóa cái cũ nhé :v):
useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll); // xóa listener đi để tránh memory leak
};
}, [state]);
mình sửa như cách của bạn, ngay lúc đầu nó thực hiện call api rất nhiều
@thanh_tuan t edit trực tiếp trên sample của bạn nhé https://codesandbox.io/s/load-more-s8elw?file=/src/ScrollLoadMore.js
@hwng bạn ơi, bạn xem giúp mình chỗ này được không:
https://codesandbox.io/s/usestate-load-more-3d5cg
Tại sao trong lần render()
cuối cùng useCallback()
của mình lại chạy vào 02 lần và có một lần log ra là null
. Mình đang chưa hiểu chỗ này, bạn xem giúp mình được không ạ
-
về việc nó return null, thì khi sử dụng inline function (trong trường hợp này là lastUser), mỗi lần render nó sẽ tạo ra function lastUser mới, nên React sẽ xoá ref cũ và tạo ref mới, khiến ta thấy hành vi: "ra null rồi lại ra node". Việc này đã đc đề cập ở official doc: https://reactjs.org/docs/refs-and-the-dom.html#caveats
-
về việc tại sao nó lại tạo 1 function lastUser mới mà ko dùng lastUser trước đó: là vì bạn chưa cung cấp dependency list cho nó, nên dù đã bọc bởi useCallback thì nó vẫn luôn tạo ra function lastUser mới ở mỗi lần render. Vì vậy, sửa cũng khá đơn giản: ta thêm dependency cho nó, chắc sẽ như nầy :v
const lastUser = useCallback(node => {
console.log('useCallback >>>', node)
}, [users]) // => users mà ko đổi thì lastUser cũng vậy
bạn có thể thêm một useEffect khác nhé useEffect(() => { window.addEventListener("scroll", handleScroll); }); Nhìn chung là bạn mới học chưa hiểu flow lắm phải không?
useEffect(() => {
console.log(state);
}, [state]);
thử xem sao ? tra google chứ chẳng biết gì về mấy cái hook này