After action is happened component gets an old state anyway. I’m not mutating the state btw. The changes appears only after I refresh the page
My component TodoList.tsx
Here’s I’m trying to get state via useEffect hook
export const TodoList: FC = () => {
const {
todoList, isLoading, isError, message
} = useTypedSelector(
(state) => state.todo
)
console.log(todoList)
const { getTodo, reset } = useActions()
useEffect(() => {
getTodo()
console.log("render")
if (isError) {
console.log(message)
}
return () => {
reset()
}
}, [])
const statusHandler = (event: React.ChangeEvent<HTMLParagraphElement>) => {
const status = event.target.innerText
if (status === "completed") {
getTodo({ complete: true })
} else if (status === "uncompleted") {
getTodo({ complete: false })
} else if (status === "all") {
getTodo()
}
}
return (
<>
...
</>
)
}
my Reducer
I’m not mutating the state also.
const initialState: TodoState = {
todoList: [],
isError: false,
isSuccess: false,
isLoading: false,
message: ""
}
export const todoReducer = (state = initialState, { type, payload }: TodoAction): TodoState => {
switch (type) {
case "GET_TODOS":
return { ...state, isLoading: true }
case "GET_TODOS_SUCCESS":
return { ...state, isLoading: false, isSuccess: true, todoList: payload }
case "GET_TODOS_ERROR":
return { ...state, isLoading: false, isError: true, message: payload.error }
case "CREATE_TODO":
return { ...state, isLoading: false }
case "CREATE_TODO_SUCCESS":
return { ...state, isLoading: false, isSuccess: true, todoList: [...state.todoList, payload]}
case "CREATE_TODO_ERROR":
return { ...state, isLoading: false, isError: true, message: payload.error }
case "TOGGLE_TODO":
return { ...state, isLoading: true }
case "TOGGLE_TODO_SUCCESS":
return {
...state, isLoading: false, isSuccess: true, todoList: state.todoList.map((todo: ITodoItem) => {
if (todo._id === payload.id) {
console.log(payload)
return {
...todo,
complete: !todo.complete
}
}
return todo
})
}
case "TOGGLE_TODO_ERROR":
return { ...state, isLoading: false, isError: true, message: payload.error }
case "DELETE_TODO":
return { ...state, isLoading: true }
case "DELETE_TODO_SUCCESS":
return {
...state, isLoading: false, isSuccess: true, todoList: state.todoList.filter(
(todo: ITodoItem) => todo._id !== payload.id
)
}
case "DELETE_TODO_ERROR":
return { ...state, isLoading: false, isError: true, message: payload.error }
case "EDIT_TODO":
return { ...state, isLoading: true }
case "EDIT_TODO_SUCCESS":
return {
...state, isLoading: false, isSuccess: true, todoList: state.todoList.map((todo: ITodoItem) => {
if (todo._id === payload.id) {
return {
...todo,
text: payload.text
}
}
return todo
})
}
case "EDIT_TODO_ERROR":
return { ...state, isLoading: false, isError: true, message: payload.error }
case "RESET_TODOS":
return { ...state, todoList: state.todoList }
default:
return state
}
}
my action creator
Here I’m making a request from my own api.
...
export const getTodo = (data?: GetTodos) => {
return async (dispatch: Dispatch<TodoAction>): Promise<void> => {
try {
dispatch({ type: "GET_TODOS", payload: {} })
let response
if (data) {
response = await todoService.getTodo((<any>data).complete)
}
response = await todoService.getTodo()
console.log(response)
dispatch({ type: "GET_TODOS_SUCCESS", payload: response })
} catch (err) {
dispatch({
type: "GET_TODOS_ERROR",
payload: { error: "Cannot fetch the todos. Please try again later" }
})
}
}
}
export const createTodo = (payload: CreateTodo) => {
return async (dispatch: Dispatch<TodoAction>): Promise<void> => {
try {
dispatch({ type: "CREATE_TODO", payload: payload })
const response = await todoService.createTodo(payload)
dispatch({ type: "CREATE_TODO_SUCCESS", payload: response })
} catch (err) {
dispatch({
type: "CREATE_TODO_ERROR",
payload: { error: "Cannot create todo. Please try again later" }
})
}
}
}
export const toggleTodo = (payload: ToggleTodo) => {
return async (dispatch: Dispatch<TodoAction>): Promise<void> => {
try {
const response = await todoService.updateTodo(payload.id, { complete: payload.complete })
dispatch({ type: "TOGGLE_TODO_SUCCESS", payload: response })
} catch (err) {
dispatch({
type: "TOGGLE_TODO_ERROR",
payload: { error: `${err}` }
})
}
}
}
...
}
all code is here: https://github.com/maridoroshuk/todos-ts
the issue