useCallback 和 IntersectionObserver 的回调在获取新值之前仍然获取 Redux 状态的旧值
useCallback and IntersectionObserver's callback still gets the old value of a Redux state before getting the new value
在我的应用程序中,对于每个交叉点,获取 10 条时间戳比日期请求 less/earlier 的消息,然后将它们取消转移到 messages
数组中。日期请求的值是 messages
状态中第一项的时间戳。这是 IntersectionObserver 代码:
const MessagesContainer = forwardRef((props, ref) => {
// ...
const messages = useSelector(state => state.messages)
const dispatch = useDispatch()
const ioCallback = useCallback((entries, observer) => {
if (entries[0].isIntersecting) {
console.log(messages[0].timestamp)
setLoading(true)
axios.post('/api/messages', { date: messages[0].timestamp })
.then(response => {
if (response.data.messages.length) {
dispatch({
type: 'ADD_TO_LIST',
name: 'messages',
payload: response.data.messages
})
ref.current.scrollTo(0, ref.current.scrollHeight / 3)
}
else {
observer.unobserve(target.current)
}
setLoading(false)
})
}
}, [messages])
useEffect(() => {
const ioOptions = {
root: ref.current,
rootMargin: '0px',
threshold: 1.0
}
const observer = new IntersectionObserver(ioCallback, ioOptions)
if (target && target.current) {
observer.observe(target.current)
}
}, [ioCallback])
// ...
})
您会注意到 ioCallback()
中的 console.log(messages[0].timestamp)
。对于每个交叉点,记录 messages
状态中第一项的时间戳。
第一个intersection/scroll没问题,它记录:
2020-06-24T20:02:41.214Z
但是下一个记录旧值和新值:
2020-06-24T20:02:41.214Z
2020-06-24T20:02:19.761Z
我需要知道如何防止 useCallback 获取旧状态值。
每次消息更改时,它都会重新创建 ioCallback,这会按预期触发 useEffect。它创建新的 IntersectionObserver,触发 ioCallback。但是老路口观察者呢?
您应该在 useEffect 挂钩中使用清除函数,它将在新的 useEffect 运行之前触发。它会停止旧的,然后你可以创建一个新的。
你可以通过返回一个函数来完成。所有引用都被保存,所以它就像将 observer.disconnect
包装在一个函数中并返回它一样简单:
useEffect(() => {
const ioOptions = {
root: ref.current,
rootMargin: '0px',
threshold: 1.0
}
const observer = new IntersectionObserver(ioCallback, ioOptions)
if (target && target.current) {
observer.observe(target.current)
}
return () => observer.disconnect();
}, [ioCallback])
在我的应用程序中,对于每个交叉点,获取 10 条时间戳比日期请求 less/earlier 的消息,然后将它们取消转移到 messages
数组中。日期请求的值是 messages
状态中第一项的时间戳。这是 IntersectionObserver 代码:
const MessagesContainer = forwardRef((props, ref) => {
// ...
const messages = useSelector(state => state.messages)
const dispatch = useDispatch()
const ioCallback = useCallback((entries, observer) => {
if (entries[0].isIntersecting) {
console.log(messages[0].timestamp)
setLoading(true)
axios.post('/api/messages', { date: messages[0].timestamp })
.then(response => {
if (response.data.messages.length) {
dispatch({
type: 'ADD_TO_LIST',
name: 'messages',
payload: response.data.messages
})
ref.current.scrollTo(0, ref.current.scrollHeight / 3)
}
else {
observer.unobserve(target.current)
}
setLoading(false)
})
}
}, [messages])
useEffect(() => {
const ioOptions = {
root: ref.current,
rootMargin: '0px',
threshold: 1.0
}
const observer = new IntersectionObserver(ioCallback, ioOptions)
if (target && target.current) {
observer.observe(target.current)
}
}, [ioCallback])
// ...
})
您会注意到 ioCallback()
中的 console.log(messages[0].timestamp)
。对于每个交叉点,记录 messages
状态中第一项的时间戳。
第一个intersection/scroll没问题,它记录:
2020-06-24T20:02:41.214Z
但是下一个记录旧值和新值:
2020-06-24T20:02:41.214Z
2020-06-24T20:02:19.761Z
我需要知道如何防止 useCallback 获取旧状态值。
每次消息更改时,它都会重新创建 ioCallback,这会按预期触发 useEffect。它创建新的 IntersectionObserver,触发 ioCallback。但是老路口观察者呢?
您应该在 useEffect 挂钩中使用清除函数,它将在新的 useEffect 运行之前触发。它会停止旧的,然后你可以创建一个新的。
你可以通过返回一个函数来完成。所有引用都被保存,所以它就像将 observer.disconnect
包装在一个函数中并返回它一样简单:
useEffect(() => {
const ioOptions = {
root: ref.current,
rootMargin: '0px',
threshold: 1.0
}
const observer = new IntersectionObserver(ioCallback, ioOptions)
if (target && target.current) {
observer.observe(target.current)
}
return () => observer.disconnect();
}, [ioCallback])