redux saga initial state first render is ==undefined - asynchronous

I am using redux saga for fetch to API but when its first render was return undefined. So list.map is not function error.
Useeffect first loop console ===> undefined '------------'
second loop=>(4) [{…}, {…}, {…}, {…}] '------------'
But list.map sometimes is throw error list.map i not function
I did use selector this component
var list = useSelector((state: any) => state.Cari.cariMusteriList.data);
async function request() {
await dispatch(getCariMusteriList());
}
useEffect(() => {
request();
}, []);
useEffect(() => {
console.log(list, '------------');
if (list) {
const formattedOptions: any[] = [];
list.map((item: any) => {
formattedOptions.push({ label: `${item.x}`, value: item.y);
});
setFormattedList(formattedOptions);
}
}, [list]);
CariReducer INITIAL state
const INIT_STATE = {
list: [],
detail: [],
};
const Cari= (state: State = INIT_STATE, action: YatActionType): any => {
switch (action.type) {
........}

Related

Trying to get "board" from "boards" use Pinia getter and receive undefined

what do i wrong?
I try to get the name of the board from Pinia Store.
I fetch the data from API onMounted in parent component (composition api setup):
onMounted(() => {
boardStore.fetchBoards();
});
and store the data in Pinia Store:
state: () => ({
boards: [],
activeBoardId: storage.getItem('activeBoardId') || null,
}),
actions: {
async fetchBoards() {
await apiClient
.getBoards()
.then((response) => {
this.boards = response.data;
return response;
})
.catch((err) => {
return err.response.data;
});
},
},
getters: {
getBoardById: (state) => {
return (id) => state.boards.find((board) => board.id === id);
},
getActiveBoardId: (state) => {
return state.activeBoardId;
},
},
In my component i try to get the name from the board via getBoardById():
import { useBoardStore } from '#stores/boardStore';
const boardStore = useBoardStore();
let board = boardStore.getBoardById(boardStore.getActiveBoardId).name
I expect to get the name of the board from the Pinia Store, but receiving undefined.
i also tried to use computed:
let board = computed(() => boardStore.getBoardById(boardStore.getActiveBoardId));
and can see the values:
ComputedRefImpl {dep: undefined, __v_isRef: true, __v_isReadonly: true, _dirty: true, _setter: ƒ, …}
...
value: Proxy
[[Target]]: Object
...
id: 95
name: "Privat"
...
But when i tried to use access i get undefined:
console.log(board)
console.log(board.name)
console.log(board.value)
console.log(board.value.name)
Also wehn i check Vue Dev Tools -> Pinia i see the "boards" Array with some items object. When i open one, i can see the "name":
boards:Array[2]
0:Object
...
id:95
name:"Privat"
...
1:Object
...
id:97
name:"Work"
...
activeBoardId:97
I suspect that either I'm trying to access them incorrectly or they're doing it too early, that the data has not yet hit the store, because async.
It's probably a small thing, but i can not find the bug or fix :-)
I expect to get the name of the board from the Pinia Store, but receiving undefined.
I found a solution, maybe not the best one, but it's work:
onMounted(async () => {
await boardStore.fetchBoards();
setBoardName();
});
watch(
() => boardStore.activeBoardId,
() => setBoardName()
);
const setBoardName = () => {
const board = computed(() => boardStore.getBoardById(boardStore.activeBoardId));
resetForm({
values: {
name: board.value.name,
},
});
};

Redux state doesn't update immediately

I have super simple question
Why my redux state doesn't update immediately?
const { reducer, actions } = createSlice({
name: "professionals",
initialState: {
loading: false,
lastFetchList: undefined,
list: undefined,
professional: undefined,
filters: {
virtual: false
}
},
reducers: {
professionalsListRequested: (professionals, action) => {
if (action.payload.withLoading) professionals.loading = true;
},
professionalsListRequestFailed: (professionals, action) => {
professionals.loading = false;
},
professionalsListReceived: (professionals, action) => {
professionals.lastFetchList = Date.now();
professionals.list = action.payload.data.dataArr;
professionals.loading = false;
},
virtualUpdated: (categories, action) => {
categories.filters.virtual = action.payload;
}
},
});
export const { virtualUpdated } = actions;
export default reducer;
it is my slice.
and here is code of the component :
const dispatch = useDispatch();
const filters = useSelector((state) => state.professionals.filters);
const handlePressOnVirtual = async () => {
console.log("Before" , filters.virtual)
await dispatch(virtualUpdated(!filters.virtual));
console.log("after" , filters.virtual)
};
when handlePressOnVirtual function is called the both console.log(s) print previous value of the state.
When you are still in handlePressOnVirtual function, you are still in a closure, so all the references will still be your existing filters
So you would need to wait for another re-render for useSelector to invoke again then the new values will come.
One way to see the latest changes is to put your log inside a useEffect:
useEffect(() => {
console.log("after" , filters.virtual)
},[filters.virtual]);

extraReducers in createSlice() in Redux Toolkit

Here's the example code from Codecademy:
import { createSlice, createAsyncThunk } from '#reduxjs/toolkit';
import { client } from '../api';
const initialState = {
todos: [],
status: 'idle'
};
export const fetchTodos = createAsyncThunk('todos/fetchTodos', async () => {
const response = await client.get('/todosApi/todos');
return response.todos;
});
const todosSlice = createSlice({
name: 'todos',
initialState,
reducers: {
addTodo: (state, action) => {
state.todos.push(action.payload);
}
},
extraReducers: {
[fetchTodos.pending]: (state, action) => {
state.status = 'loading';
},
[fetchTodos.fulfilled]: (state, action) => {
state.status = 'succeeded';
state.todos = state.todos.concat(action.payload);
}
}
});
I'm confused about what fetchTodos.pending and fetchTodos.fulfilled mean as computed properties. I don't see that fetchTodos has those attributes. What is going on?
Those are generated by createAsyncThunk
Check out the RDK docs on createAsyncThunk
Parameters#
createAsyncThunk accepts three parameters: a string action type value, a payloadCreator callback, and an options object.
type
A string that will be used to generate additional Redux action type
constants, representing the lifecycle of an async request:
For example, a type argument of 'users/requestStatus' will generate these
action types:
pending: 'users/requestStatus/pending'
fulfilled: 'users/requestStatus/fulfilled'
rejected: 'users/requestStatus/rejected'

Redux Thunk Typescript cannot dispatch with Async

I make a sample testing for redux-thunk (no react, only console app), the code is here:
interface IStartLoadAction extends Action<"START"> {
}
interface IEndLoadAction extends Action<"END"> {
}
type LoadActionTypes = IStartLoadAction | IEndLoadAction;
function startLoad(): LoadActionTypes {
return {type: "START"};
}
function endLoad(): LoadActionTypes {
return {type: "END"};
}
const loadReducer: Reducer<ILoadState | undefined, LoadActionTypes> = (
state = initLoadState,
action: LoadActionTypes) => {
switch (action.type) {
case "START":
return {isLoading: !state.isLoading};
case "END":
return {isLoading: !state.isLoading};
default:
return {isLoading: false};
}
};
const rootReducer = combineReducers({
loader: loadReducer,
});
const store = createStore(rootReducer, applyMiddleware(Thunk));
const fetchData = (): ThunkAction<Promise<void>, ILoadState, null, AnyAction> => {
return async (dispatch: ThunkDispatch<{}, {}, AnyAction>): Promise<void> => {
return new Promise<void>((resolve) => {
dispatch(startLoad());
console.log('start....');
setTimeout(() => {
dispatch(<some actions>);
}, 2000);
dispatch(endLoad());
console.log('end....');
resolve();
});
};
};
But when I call store.dispatch(fetchData());, It return an error:
Argument of type 'ThunkAction, ILoadState, null,
AnyAction>' is not assignable to parameter of type 'AnyAction'.
How to let it work? Thanks (I wont use it in react env, server side only)
The sample of Redux official web site is "js", but not "ts", so I don't know how to translate it.

Dispatch in middleware leads to action with wrong type

I'm trying to create a simple middleware to handle socket events.
const join = (channel) => (dispatch) => {
dispatch({
type: 'ACTION-1',
socketChannel: {...},
events: [...],
});
};
I dispatch this action that triggers it. And now when the dispatch method was called in my middleware with type 'ACTION-2' and received socketData as a payload, I see in my console what 'ACTION-1' was triggered twice and in the last time it is came with my socketData payload.
I wonder why 'ACTION-1' was registered instead 'ACTION-2' and how I can fix it? I would appreciate your help.
import { socket } from 'services/socket';
const socketMiddleware = ({ dispatch }) => next => (action) => {
const {
channel,
events, // an array of events for the channel
...rest
} = action;
if (typeof action === 'function' || !channel) {
return next(action);
}
const {
type,
name,
} = channel;
const channelInstance = socket.instance[type](name);
events.forEach((event) => {
const handleEvent = (socketData) => {
dispatch({ type: 'ACTION-2', socketData, ...rest });
};
channelInstance.listen(event.name, handleEvent);
});
return next(action);
};
export {
socketMiddleware
};
looks like you are not pathing the channel in your initial dispatch and you are failing your middleware finishes inside this if:
if (typeof action === 'function' || !channel) {
return next(action);
}
in order to fix this you should add channel in your dispatch:
const join = (channel) => (dispatch) => {
dispatch({
type: 'ACTION-1',
socketChannel: {...},
events: [...],
channel: { type: '...', name: '...' }
});
};

Resources