dispatch函数调用后未触发useEffect钩子的技术问题咨询
问题:useEffect依赖含dispatch但调用dispatch后未触发
我在useEffect的依赖数组中加入了reducer的dispatch函数,但调用dispatch后useEffect并未触发。相关代码如下:
useEffect代码
useEffect( function fetchNotes() { fetch('/notes', {method: 'GET'}) .then(response => response.json()) .then(data => { data.sort((a, b) => a.title.localeCompare(b.title)); if(!isArchived) { const activeNotes = data.filter(n => !n.archived); const uniqueTags = [...new Set(activeNotes.flatMap(note => note.tags))]; setTagFilter(uniqueTags); dispatch({type: 'CHOOSE', arr: activeNotes}); } else { const archivedNotes = data.filter(n => n.archived); const uniqueTags = [...new Set(archivedNotes.flatMap(note => note.tags))]; setTagFilter(uniqueTags); dispatch({type: 'CHOOSE', arr: archivedNotes}); } }) .catch(error => { console.error('Error fetching notes:', error); }); }, [dispatch, isArchived ] );
Reducer代码
const reducer = (state, action) => { switch(action.type) { case 'ADD': return [...state, action.newNote]; case 'DELETE': return state.filter(note => note.id !== action.id); case 'CHOOSE': return action.arr case 'CHANGE TAGS': return state.map(note => { if(note.id === action.id) { return {...note, tags: action.newTags} } else { return note } }) case 'ARCHIVE': return state.map(note => (note.id === action.id ? { ...note, archived: action.archived } : note)); default: return state } } export default reducer
解答
原因分析
dispatch 是 useReducer 钩子返回的稳定函数,组件每次重渲染时它的引用都不会改变。所以把它加入useEffect的依赖数组,不会让useEffect在调用dispatch时触发——因为dispatch本身没变化,useEffect的依赖条件没满足更新触发的要求。
解决方案
如果你的需求是当reducer管理的state变化时触发useEffect,应该把reducer的state加入依赖数组:
const [state, dispatch] = useReducer(reducer, initialState); useEffect( function fetchNotes() { // 你的逻辑代码 }, [dispatch, isArchived, state ] // 加入state );
如果不需要监听整个state,也可以根据实际需求监听state中的特定字段,比如state.length或者某个特定属性,避免不必要的触发。
要明确:useEffect的触发条件是依赖数组中的值发生引用或值的变化,dispatch本身不会变化,所以它无法触发useEffect的重新执行。
内容的提问来源于stack exchange,提问作者RonanFilloy
相关产品推荐
相关产品推荐

