我在不同的组件中使用这个自定义 http Hook 。
function useHttp(requestFunction, startWithPending = false) {
const httpState = useSelector((state) => state.http);
const dispatch = useDispatch();
const sendRequest = useCallback(
async function (requestData) {
dispatch(httpActions.loading(startWithPending));
try {
const responseData = await requestFunction(requestData);
dispatch(httpActions.success(responseData));
} catch (error) {
dispatch(httpActions.error(error.message || "Something went wrong!!!"));
}
},
[dispatch, requestFunction, startWithPending]
);
return {
sendRequest,
...httpState,
};
}
我正在使用 Redux 工具包(我的 http 操作)管理状态。
const initialHttpState = {
status: null,
data: null,
error: null,
};
const httpSlice = createSlice({
name: 'http',
initialState: initialHttpState,
reducers: {
loading(state, action){
state.status = action.payload ? 'pending' : 'null';
state.data = null;
state.error = null;
},
success(state, action){
state.status = 'completed';
state.data = action.payload;
state.error = 'null'
},
error(state, action){
state.status = 'error';
state.data = null;
state.error = action.payload;
}
}
})
我在多个组件的 useEffect 中使用这个钩子(Hook):
const { sendRequest, data, status, error } = useHttp(getProducts, true);
useEffect(() => {
sendRequest();
}, [sendRequest]);
我的问题是,由于不同的组件使用相同的钩子(Hook),每当我尝试在组件内调用此自定义钩子(Hook)时,使用相同钩子(Hook)的任何其他组件都会重新渲染,这会导致我的应用程序崩溃(无法读取未定义错误的属性),因为如您所见,我将响应数据覆盖到同一位置,并且状态也在变化。
如何避免这个重新渲染问题?在我的组件内部,如何检查此重新渲染需求是来自其他组件还是组件本身?或者我如何改变我的状态管理结构来处理这个问题?
最佳答案
这是使用单个全局状态不正是您想要从钩子(Hook)中得到的情况之一。每个 useHttp 钩子(Hook)都应该有自己的内部状态来管理请求并减轻处理任何响应值的责任。从 Redux 代码到使用 useReducer
Hook 是一个相当简单的转换,因此每个 useHttp
Hook 都有自己的状态和 reducer 逻辑。
示例:
const initialHttpState = {
status: null,
data: null,
error: null,
};
const reducer = (state, action) => {
switch(action.type) {
case "loading":
return {
status: action.payload ? 'pending': null,
data: null,
error: null,
};
case "success":
return {
...state,
status: 'completed',
data: action.payload,
error: null,
};
case "error":
return {
...state,
status: 'error',
data: null,
error: action.payload,
};
default:
return state;
}
};
...
const useHttp = (requestFunction, startWithPending = false) => {
const [httpState, dispatch] = React.useReducer(reducer, initialHttpState);
const sendRequest = useCallback(
async function (requestData) {
dispatch(httpActions.loading(startWithPending));
try {
const responseData = await requestFunction(requestData);
dispatch(httpActions.success(responseData));
} catch (error) {
dispatch(httpActions.error(error.message || "Something went wrong!!!"));
}
},
[dispatch, requestFunction, startWithPending]
);
return {
sendRequest,
...httpState,
};
}
关于reactjs - 避免由于其他组件使用的自定义钩子(Hook)而重新渲染组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71572239/