使用长 运行 任务反应 useEffect 挂钩并合并状态
React useEffect hook with long running task and merge state
我有一个用户可以使用拖放上传文件的场景。
我使用一个带有空 depedency 数组的效果来设置一个 RXJS 订阅来处理丢弃的文件和上传时间:
const [attachments, setAttachments] = useState([])
useEffect(() => {
...
fileUploadSubject.subscribe(newAttachments => {
setAttachments([...attachments,newAttachments])
})
...
return () => {
subscriptions.forEach(s => {
s.unsubscribe()
})
}
},[])
问题是效果依赖于 attachments
以及 setAttachments
函数。
如果我将 attachments
添加到依赖项数组,我将取消订阅现有的上传。此外,attachment
状态由于其关闭而不会在效果内部更新。
我该如何处理这种情况?我想过很多方法,但似乎找不到简单的方法。
If I add attachments to the dependency array I will unsubscribe to the existing uploads
不知道为什么取消订阅,不熟悉fileUploadSubject.subscribe
Also attachment state is not updated inside the effect due to its closure
您可以 useReducer
而不是 useState
,这样您就不需要依赖效果中的状态。
也许是这样的:
function reducer(state, action) {
switch (action.type) {
case "ADD_ATTACH":
return [...state, action.payload];
default:
throw new Error();
}
}
function App() {
const [attachments, dispatch] = useReducer(reducer, []);
useEffect(() => {
// ...
fileUploadSubject.subscribe(newAttachments => {
dispatch({ type: "ADD_ATTACH", payload: newAttachments });
});
// ...
return () => {
subscriptions.forEach(s => {
s.unsubscribe();
});
};
}, [/*fileUploadSubject?, subscriptions? */]);
return <div>{ /* some UI */ }</div>;
}
我仍然认为你的效果不依赖于任何东西很奇怪,确保 subscriptions
和 fileUploadSubject
真的不应该在 dependencies 数组中。
useState
的setState函数支持functional updates形式:
const [attachments, setAttachments] = useState([])
useEffect(() => {
...
const subscription = fileUploadSubject.subscribe(newAttachments => {
setAttachments((oldAttachments) => [...oldAttachments, newAttachments])
})
...
return () => subscription.unsubscribe()
}, [setAttachments, fileUploadSubject])
永远不会改变的函数(即这里的两个)可以在依赖列表中省略,但我更喜欢列出它们以防止忘记一些依赖。有 eslint rules 的难度。
我有一个用户可以使用拖放上传文件的场景。
我使用一个带有空 depedency 数组的效果来设置一个 RXJS 订阅来处理丢弃的文件和上传时间:
const [attachments, setAttachments] = useState([])
useEffect(() => {
...
fileUploadSubject.subscribe(newAttachments => {
setAttachments([...attachments,newAttachments])
})
...
return () => {
subscriptions.forEach(s => {
s.unsubscribe()
})
}
},[])
问题是效果依赖于 attachments
以及 setAttachments
函数。
如果我将 attachments
添加到依赖项数组,我将取消订阅现有的上传。此外,attachment
状态由于其关闭而不会在效果内部更新。
我该如何处理这种情况?我想过很多方法,但似乎找不到简单的方法。
If I add attachments to the dependency array I will unsubscribe to the existing uploads
不知道为什么取消订阅,不熟悉fileUploadSubject.subscribe
Also attachment state is not updated inside the effect due to its closure
您可以 useReducer
而不是 useState
,这样您就不需要依赖效果中的状态。
也许是这样的:
function reducer(state, action) {
switch (action.type) {
case "ADD_ATTACH":
return [...state, action.payload];
default:
throw new Error();
}
}
function App() {
const [attachments, dispatch] = useReducer(reducer, []);
useEffect(() => {
// ...
fileUploadSubject.subscribe(newAttachments => {
dispatch({ type: "ADD_ATTACH", payload: newAttachments });
});
// ...
return () => {
subscriptions.forEach(s => {
s.unsubscribe();
});
};
}, [/*fileUploadSubject?, subscriptions? */]);
return <div>{ /* some UI */ }</div>;
}
我仍然认为你的效果不依赖于任何东西很奇怪,确保 subscriptions
和 fileUploadSubject
真的不应该在 dependencies 数组中。
useState
的setState函数支持functional updates形式:
const [attachments, setAttachments] = useState([])
useEffect(() => {
...
const subscription = fileUploadSubject.subscribe(newAttachments => {
setAttachments((oldAttachments) => [...oldAttachments, newAttachments])
})
...
return () => subscription.unsubscribe()
}, [setAttachments, fileUploadSubject])
永远不会改变的函数(即这里的两个)可以在依赖列表中省略,但我更喜欢列出它们以防止忘记一些依赖。有 eslint rules 的难度。