#reactjs #react-redux #redux-thunk #redux-toolkit
Вопрос:
Я хотел бы вызвать функцию обратного вызова после react-redux
«s useDispatcher
«, но я не знаю, как я могу это сделать. Вот код, который я хотел бы вызвать props.changeFocusOnEnter()
в качестве обратного вызова для dispatcher
:
const dispatcher = useDispatch();
const editItemOnKeyDown = (e, item, i) => {
if (e.key === "Enter") {
dispatcher(addNewItemToList({ title: "", withIndent: false, parentId: props.parentId }))
props.changeFocusOnEnter();
}
};
На самом деле мне бы хотелось чего-то подобного:
dispatcher(addNewItemToList({ title: "", withIndent: false, parentId: props.parentId })).then(()=>{ props.changeFocusOnEnter();})}
Я поделюсь своим кодом для лучшего понимания структуры:
store.js
import { applyMiddleware, combineReducers, compose, configureStore } from "@reduxjs/toolkit";
import { listReducer } from "./reducers/listReducer";
import thunk from 'redux-thunk';
const rootReducer = combineReducers({
listReducer,
})
export const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(thunk),
})
listReducer.js
import { createReducer } from "@reduxjs/toolkit";
import {
ADD_ITEM_TO_LIST,
UPDATE_ITEM_IN_LIST,
DELETE_ITEM_FROM_LIST,
ADD_ITEM_TO_LIST_WITH
} from "../actionCreators/listActionCreator";
const addNewItemToList = (list, payload) => {
let lastId = list.length 1;
const item = {
id: lastId,
title: payload.title,
indent: false,
parentId: payload.parentId
};
if (!payload.atIndex) {
list.push(item);
} else {
list.splice(payload.atIndex, 0, item);
}
return list;
};
const updateItemInList = (list, payload) => {
let currentItem = list.filter((x) => x.id === payload.id)[0];
currentItem.title = payload.title;
currentItem.indent = payload.indent;
let currentItemIndex = list.findIndex((x) => x.id === currentItem.id);
list[currentItemIndex] = currentItem;
return list;
};
const deleteItemFromList = (list, payload) => {
console.log(payload);
let currentItemIndex = -1;
if (payload.id) currentItemIndex = list.findIndex((x) => x.id === payload.id);
else currentItemIndex = payload.index;
list.splice(currentItemIndex, 1);
return list;
};
export const listReducer = createReducer([], (builder) => {
builder
.addCase(ADD_ITEM_TO_LIST, (state, action) => {
return addNewItemToList(state, action.payload);
})
.addCase(UPDATE_ITEM_IN_LIST, (state, action) => {
return updateItemInList(state, action.payload);
})
.addCase(DELETE_ITEM_FROM_LIST, (state, action) => {
deleteItemFromList(state, action.payload);
});
});
listActionCreator.js
import { createAction, PayloadAction } from "@reduxjs/toolkit";
export const DELETE_ITEM_FROM_LIST = "DELETE_ITEM_FROM_LIST";
export const ADD_ITEM_TO_LIST = "ADD_ITEM_TO_LIST";
export const UPDATE_ITEM_IN_LIST = "UPDATE_ITEM_IN_LIST";
export const addNewItemToList = createAction(ADD_ITEM_TO_LIST);
export const deleteItemFromList = createAction(DELETE_ITEM_FROM_LIST);
export const updateItemInList = createAction(UPDATE_ITEM_IN_LIST);
У вас есть какие-либо предложения по изменению конфигурации и достижению моей цели?
Комментарии:
1.
addNewItemToList
создатель действий, созданный с помощьюcreateAction
, — это просто функция, которая возвращает простой объект, это НЕ обещание, это синхронизация. Вы можете продолжить выполнение других кодов после отправки этого действия. Если вы хотите использовать обещание, вам следует использоватьcreateAsyncThunk
2. @slideshowp2 Спасибо за внимание.
props.changeFocusOnEnter()
это не асинхронная функция, но она должна запускаться после изменения состояния приложения. Как я могу использовать обещание в этой ситуации?
Ответ №1:
Вы можете использовать useEffect
в компоненте props.changeFocusOnEnter
, на который подписан asnd listReducer
const dispatcher = useDispatch();
const list = useSelector(s=>s.listReducer)
useEffecct(()=> { props.changeFocusOnEnter() } , [ list ])
const editItemOnKeyDown = (e, item, i) => {
if (e.key === "Enter") {
dispatcher(addNewItemToList({ title: "", withIndent: false, parentId: props.parentId }))
}
};
(Эта часть может быть изменена для других желаемых поведений UX, таких как игнорирование первого рендеринга и т. Д., Но использование useEffect
в целом является обычным использованием крючка)
Комментарии:
1. Я не хотел бы использовать
useEffect
, потому что у меня есть некоторые другие события, которые повлияют на состояние в этом компоненте. Так что , если я используюuseEffect
,props.changeFocusOnEnter()
будет выполняться каждый раз, когда я меняюсьstate
.