useReducer修改isLoading状态后依赖的useEffect未触发无输出问题
问题原因
一共存在3处核心问题导致无输出:
- 拼写错误导致代码直接抛出异常,无法正常运行逻辑
useCurrentRequesthook返回值中引用了未定义的weatherRequestState变量,实际定义的状态变量为requestStateCallingComponent中错误调用了不存在的useCurrentWeatherhook,实际导入的hook名为useCurrentRequest
- 同步连续触发状态更新被React批量合并
在getData中同步先后触发SEND和RESPONSE类型的action,React会将两次状态更新合并执行,最终isLoading的变化为false → true → false,前后最终值一致,不会触发依赖isLoading的副作用执行。
解决步骤
- 修正所有拼写错误
- 为状态更新添加异步间隔,避免批量合并(符合真实接口请求的异步场景)
修正后的useCurrentRequest代码
import {useReducer, useCallback, useEffect} from 'react'; export const initialState = { isLoading: false, data: null, } const requestReducer = (state = initialState, action) => { switch (action.type) { case 'SEND': return {...state, isLoading: true, }; case 'RESPONSE': return {...state, isLoading: false, data: action.responseData }; default: return state; } } //封装了reducer状态修改逻辑的自定义hook const useCurrentRequest = () => { const [requestState, dispatchRequestActions] = useReducer(requestReducer, initialState); useEffect(() => { console.log("hook内isLoading:", requestState.isLoading); }, [requestState.isLoading]); const initializeLoading = useCallback(() => { dispatchRequestActions({type: 'SEND'}); },[dispatchRequestActions]); const getRequestResponse = useCallback(() => { // 模拟异步接口请求 setTimeout(() => { dispatchRequestActions({type: 'RESPONSE', responseData: {someData:true}}); }, 300) }, [dispatchRequestActions]); return { initializeLoadingPointer: initializeLoading, getRequestResponsePointer: getRequestResponse, isLoading: requestState.isLoading, data: requestState.data, } } export default useCurrentRequest;
修正后的CallingComponent代码
import {useEffect} from "react"; import useCurrentRequest from "../hooks/useCurrentRequest"; const CallingComponent = props => { const {initializeLoadingPointer, getRequestResponsePointer, isLoading} = useCurrentRequest(); const getData = () => { initializeLoadingPointer(); getRequestResponsePointer(); }; useEffect(() => { console.log("组件内isLoading:", isLoading); }, [isLoading]); return (<button onClick={getData}>Get data</button>) }
修正后点击按钮会依次打印true、false,符合预期。
内容的提问来源于stack exchange,提问作者David Galvis Sandoval
相关产品推荐
相关产品推荐

