useReducer() 更改的 属性 状态永远不会显示更改,即使这些更改已被分派
A property of the state changed by useReducer() is never displaying changes even when those are dispatched
我一直在使用 useReducer()
以便我可以在一些组件之间共享一些状态。在 requestReducer
中有一个 属性 称为 isLoading
,其中 default/initial 状态设置为 false
。有两个函数将操作分派给 reducer(initializeLoading
:将 isLoading 更改为 true
,以及 getRequestResponse
:将 isLoading 更改回 false
)。但是当 reducer 用来初始化加载的函数 -initializeLoading
- 被 CallingComponent
调用时,它使用这些函数的指针来调用它们; useEffect
中的状态变化(它依赖于 requestState.isLoading
),永远不会显示在控制台中,也不会在 useCurrentRequest
挂钩和 CallingComponent
中调用,什么时候应该被调用;因为在第一次调用 isLoading
prop 时,从 false
变成 true
,通过 SEND
action.type
。此外,当从 CallingComponent
调用 getRequestResponse
函数(启动 RESPONSE
action.type
=> isLoading
= false
)时,它应该从true
到 false
,因此它也应该由应该捕获这些更改的 useEffect
显示。但是什么都没有发生,而是什么也没有显示。
这是 useCurrentRequest
和 requestReducer
:
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;
}
}
//This is the hook with the logic that sets state using the reducer
const useCurrentRequest = () => {
const [requestState, dispatchRequestActions] = useReducer(requestReducer, initialState);
//The loading change of state is not displayed in the console
useEffect(() => {
console.log(requestState.isLoading);
}, [requestState.isLoading]);
const initializeLoading = useCallback(() => {
dispatchRequestActions({type: 'SEND'});
console.log(requestState);
},[]);
const getRequestResponse = useCallback(() => {
//some call to an api happens here
//Then the response is given using the reducer
dispatchRequestActions({type: 'RESPONSE', responseData: {someData:true}});
}, []);
return {
initializeLoadingPointer: initializeLoading,
getRequestResponsePointer: getRequestResponse,
isLoading: weatherRequestState.isLoading,
data: weatherRequestState.data,
}
}
export default useCurrentRequest;
这里是 CallingComponent
,它使用 useCurrentRequest
钩子提供的函数指针:
import {useEffect} from "react";
import useCurrentRequest from "../hooks/useCurrentRequest";
const CallingComponent = props => {
const {initializeLoadingPointer, getRequestResponsePointer, isLoading} = useCurrentWeather();
const getData = () => {
initializeLoadingPointer();
getRequestResponsePointer();
};
useEffect(() => {
console.log(isLoading);
}, [isLoading]);
return (<button onClick={getData}>Get data</button>)
}
问题基本上是单击 Get Data
按钮后没有显示任何内容,而应该在控制台中显示 true
和 false
的顺序,因为 useEffect()
取决于 isLoading
并且那些函数发生变化 isLoading
,但同样没有显示任何内容。
我将不胜感激。
谢谢! :)
我终于通过使用async-await解决了这个问题,问题是由于对那些正在修改reducer的函数的请求是同步发生的,所以只有在它们都完成后才会更新状态,并且函数那个叫他们的也已经结束了。所以我所做的是通过 de async-await 模式使用 promises 来阻止一些代码片段。基本上,我只修改了 useCurrentRequest()
钩子,用这个替换了这两个函数:
const useCurrentRequest = () => {
const [requestState, dispatchRequestActions] = useReducer(requestReducer, initialState);
useEffect(() => {
console.log(requestState.isLoading);
}, [requestState.isLoading]);
const sendRequestAsync = useCallback(async (city) => {
const query = `weather?q=${city}`;
console.log(query);
dispatchRequestActions({ type: "SEND" });
try {
const result = await fakeRequest();
dispatchRequestActions({ type: "RESPONSE", responseData: result.data });
} catch (error) {
dispatchRequestActions({ type: "ERROR", errorMessage: error.message });
}
}, []);
const fakeRequest = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ data: "data" });
}, 1000);
});
};
return {
getRequestResponsePointer: sendRequestAsync,
isLoading: weatherRequestState.isLoading,
data: weatherRequestState.data,
}
}
export default useCurrentRequest;
这样我就可以使用 useEffect()
挂钩看到更改。
我一直在使用 useReducer()
以便我可以在一些组件之间共享一些状态。在 requestReducer
中有一个 属性 称为 isLoading
,其中 default/initial 状态设置为 false
。有两个函数将操作分派给 reducer(initializeLoading
:将 isLoading 更改为 true
,以及 getRequestResponse
:将 isLoading 更改回 false
)。但是当 reducer 用来初始化加载的函数 -initializeLoading
- 被 CallingComponent
调用时,它使用这些函数的指针来调用它们; useEffect
中的状态变化(它依赖于 requestState.isLoading
),永远不会显示在控制台中,也不会在 useCurrentRequest
挂钩和 CallingComponent
中调用,什么时候应该被调用;因为在第一次调用 isLoading
prop 时,从 false
变成 true
,通过 SEND
action.type
。此外,当从 CallingComponent
调用 getRequestResponse
函数(启动 RESPONSE
action.type
=> isLoading
= false
)时,它应该从true
到 false
,因此它也应该由应该捕获这些更改的 useEffect
显示。但是什么都没有发生,而是什么也没有显示。
这是 useCurrentRequest
和 requestReducer
:
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;
}
}
//This is the hook with the logic that sets state using the reducer
const useCurrentRequest = () => {
const [requestState, dispatchRequestActions] = useReducer(requestReducer, initialState);
//The loading change of state is not displayed in the console
useEffect(() => {
console.log(requestState.isLoading);
}, [requestState.isLoading]);
const initializeLoading = useCallback(() => {
dispatchRequestActions({type: 'SEND'});
console.log(requestState);
},[]);
const getRequestResponse = useCallback(() => {
//some call to an api happens here
//Then the response is given using the reducer
dispatchRequestActions({type: 'RESPONSE', responseData: {someData:true}});
}, []);
return {
initializeLoadingPointer: initializeLoading,
getRequestResponsePointer: getRequestResponse,
isLoading: weatherRequestState.isLoading,
data: weatherRequestState.data,
}
}
export default useCurrentRequest;
这里是 CallingComponent
,它使用 useCurrentRequest
钩子提供的函数指针:
import {useEffect} from "react";
import useCurrentRequest from "../hooks/useCurrentRequest";
const CallingComponent = props => {
const {initializeLoadingPointer, getRequestResponsePointer, isLoading} = useCurrentWeather();
const getData = () => {
initializeLoadingPointer();
getRequestResponsePointer();
};
useEffect(() => {
console.log(isLoading);
}, [isLoading]);
return (<button onClick={getData}>Get data</button>)
}
问题基本上是单击 Get Data
按钮后没有显示任何内容,而应该在控制台中显示 true
和 false
的顺序,因为 useEffect()
取决于 isLoading
并且那些函数发生变化 isLoading
,但同样没有显示任何内容。
我将不胜感激。
谢谢! :)
我终于通过使用async-await解决了这个问题,问题是由于对那些正在修改reducer的函数的请求是同步发生的,所以只有在它们都完成后才会更新状态,并且函数那个叫他们的也已经结束了。所以我所做的是通过 de async-await 模式使用 promises 来阻止一些代码片段。基本上,我只修改了 useCurrentRequest()
钩子,用这个替换了这两个函数:
const useCurrentRequest = () => {
const [requestState, dispatchRequestActions] = useReducer(requestReducer, initialState);
useEffect(() => {
console.log(requestState.isLoading);
}, [requestState.isLoading]);
const sendRequestAsync = useCallback(async (city) => {
const query = `weather?q=${city}`;
console.log(query);
dispatchRequestActions({ type: "SEND" });
try {
const result = await fakeRequest();
dispatchRequestActions({ type: "RESPONSE", responseData: result.data });
} catch (error) {
dispatchRequestActions({ type: "ERROR", errorMessage: error.message });
}
}, []);
const fakeRequest = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ data: "data" });
}, 1000);
});
};
return {
getRequestResponsePointer: sendRequestAsync,
isLoading: weatherRequestState.isLoading,
data: weatherRequestState.data,
}
}
export default useCurrentRequest;
这样我就可以使用 useEffect()
挂钩看到更改。