Reducers aren't triggered upon dispatch, Redux Toolkit - react-redux

I am creating a simple todo and i'm using redux toolkit.
My issue is that it seems not to work, there is no error. It just doesn't work.
TaskPane.tsx
dispatch(addTask(task));
TaskSlice.tsx
const taskSlice = createSlice({
name: 'tasks',
initialState,
reducers: {
addTask: (state, action: PayloadAction<string>) => {
console.log('Add task');
state.tasksItems = [
...state.tasksItems,
{
id: Date.now(),
title: action.payload,
status: 'todo',
},
];
},
justPrint: state => {
console.log('I am called.');
},
},
});
Nothing is being printed on console when i dispatch both actions.
I have another slice for modals and it works properly.

Related

Dispatch actions from a custom hook using useQuery

I'm trying to write a custom hook that uses useQuery from react-query. The custom hook takes in the id of an employee and fetches some data and returns it to the consuming component. I want to be able to dispatch a redux action to show a loading indicator or show an error message if it fails. Here is my custom hook.
export default function useEmployee(id) {
const initial = {
name: '',
address: '',
}
const query = useQuery(['fetchEmployee', id], () => getEmployee(id), {
initialData: initial,
onSettled: () => dispatch(clearWaiting()),
onError: (err) => dispatch(showError(err)),
})
if (query.isFetching || query.isLoading) {
dispatch(setWaiting())
}
return query.data
}
When I refresh the page, I get this error in the browser's console and I'm not sure how to fix this error?
Warning: Cannot update a component (`WaitIndicator`) while rendering a different component (`About`).
To locate the bad setState() call inside `About`, follow the stack trace as described in
The issue is likely with dispatching the setWaiting action outside any component lifecycle, i.e. useEffect. Move the dispatch logic into a useEffect hook with appropriate dependency.
Example:
export default function useEmployee(id) {
const initial = {
name: '',
address: '',
};
const { data, isFetching, isLoading } = useQuery(['fetchEmployee', id], () => getEmployee(id), {
initialData: initial,
onSettled: () => dispatch(clearWaiting()),
onError: (err) => dispatch(showError(err)),
});
useEffect(() => {
if (isFetching || isLoading) {
dispatch(setWaiting());
}
}, [isFetching, isLoading]);
return data;
}

Data not showing on vue.js component using laravel api

I'm trying to get the data from database using an API, but there are no output on my vue controller.
Am I doing this right?
I think I'm assigning the scheduleList the wrong way.
I'm very new to vue.js and API, I want to know what I'm doing wrong here.
Controller
public function schedules(){
return Schedule::all();
}
api.php
Route::get('schedules', 'CalendarController#schedules');
Vue Component
<script>
import axios from 'axios'
export default {
data() {
return {
schedules: [],
scheduleList: [
{
id: schedules.id,
title: schedules.title,
category: schedules.category,
start: schedules.start,
end: schedules.end
},
],
};
},
methods: {
loadSchedules() {
axios.get('/api/schedules')
.then((response) => {
this.schedules = response.data;
})
}
},
mounted() {
this.loadSchedules();
}
};
</script>
<style>
</style>
The issue is in your data option because you're referencing schedules which is undefined, I'm sure that you're meaning this.schedules but doing that will not solve the issue because at first rendering this.schedules is an empty array, another problem that you're referencing at as object in scheduleList items using schedules.id, if the schedules property is an array i recommend the following solution :
<script>
import axios from 'axios'
export default {
data() {
return {
schedules: [],
scheduleList: [],
};
},
methods: {
loadSchedules() {
axios.get('/api/schedules')
.then((response) => {
this.schedules = response.data;
let schedule=this.schedules[0]
this.scheduleList.push({
id: schedule.id,
title: schedule.title,
category: schedule.category,
start: schedule.start,
end: schedule.end
})
})
}
},
mounted() {
this.loadSchedules();
}
};
</script>
always catch errors if you do promises.
loadSchedules() {
axios.get('/api/schedules')
.then((response) => {
this.schedules = response.data;
})
.catch(error => {
console.log(error)
})
inside your error you can better see whats going wrong.
other way is the "network" tab in your browser where you can trace your api request

Is there a way to add conversation history when connecting to direct line?

We are using botframework-webchat v4. Is there any way to provide history that will be shown up in the chat?
This is currently what I have, but its not working, not sure what format should be for activities in store.
const store = window.WebChat.createStore(
{
activities: ['{"type":"message",...}']
},
({ dispatch }: { dispatch: any }) => (next: any) => (action: any) => {
if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
const { activity } = action.payload;
if (activity.type === 'event' && activity.name === 'sample:backchannel') {
alert(JSON.stringify(activity, null, 2));
}
}
return next(action);
}
)
window.WebChat.renderWebChat(
{
directLine: this.directLine,
userID: this.userId,
styleOptions,
store
},
this.botWindowElement.nativeElement
);
Thanks in advance!!
You're solution above will, technically, work. Although, it's not very scalable in the long run. I would recommend you look over this BotFramework-WebChat experimental sample, Conversation History. It utilizes the sendConversationHistory API. This sample is a bit on the complex side, but will do precisely what you are wanting, i.e. load a previous user's conversation when a new session is started.
If you are wanting to reconnect a previous conversation (meaning continue a conversation using the same conversationId) then you should be aware that the Direct Line service has certain limitations. Reconnecting will only work for up to 14 days after the last activity to that conversation and only 24 hours if activities are present.
Hope of help!
#StevenKanberg Thanks for the help!
I found the answer in source code of BotFramework-WebChat.
Here is the sample,
test('absolute timestamp', async () => {
const activities = [
{
type: 'message',
id: '6266x5ZXhXkBfuIH0fNx0h-o|0000000',
timestamp: '2019-08-08T16:41:12.9397263Z',
from: {
id: 'dl_654b35e09ab4149595a70aa6f1af6f50',
name: '',
role: 'user'
},
textFormat: 'plain',
text: 'echo "Hello, World!"'
},
{
type: 'message',
id: '6266x5ZXhXkBfuIH0fNx0h-o|0000001',
timestamp: '2019-08-08T16:41:13.1835518Z',
from: {
id: 'webchat-mockbot',
name: 'webchat-mockbot',
role: 'bot'
},
text: 'Echoing back in a separate activity.'
},
{
type: 'message',
id: '6266x5ZXhXkBfuIH0fNx0h-o|0000002',
timestamp: '2019-08-08T16:41:13.3963019Z',
from: {
id: 'webchat-mockbot',
name: 'webchat-mockbot',
role: 'bot'
},
text: 'Hello, World!'
}
];
const styleOptions = { timestampFormat: 'absolute' };
const { driver } = await setupWebDriver({ storeInitialState: { activities }, props: { styleOptions } });

Nativescript angular navigate to previous component

I have a ns-angular app that is structured as follows :
in the app.component I have a master page-router-outlet with 2 pages
Login
Main
Routing is configured in the following way :
const routes: Routes = [
{ path: '', redirectTo: 'start', pathMatch: 'full' },
{ path: 'start', loadChildren: './views/login/start.module#StartModule' },
{ path: 'main', loadChildren: './views/main/main.module#MainModule' }
];
#NgModule({
imports: [NativeScriptRouterModule.forRoot(routes)],
exports: [NativeScriptRouterModule]
})
export class AppRoutingModule { }
In the main component I have static action bar and a child router-outlet that navigates between these components.
Again routing is defined as :
const mainRoutes: Routes = [
{
path: '', component: MainComponent, children: [
{ path: '', redirectTo: 'main/explore', pathMatch: 'full' },
{ path: 'camera', loadChildren: './camera/camera.module#CameraModule' },
{ path: 'explore', loadChildren: './explore/explore.module#ExploreModule' }
]
}
];
export const MainRouting: ModuleWithProviders = RouterModule.forChild(mainRoutes);
What currently happens is that if I am in the - let's say- explore component ( /main/explore ), I navigate to the the camera component ( /main/camera ) and I press back on my android device, instead of going back to the explore component I go to the start module.
I read the documentation on angular navigation, but even with the following code
android.on(AndroidApplication.activityBackPressedEvent, (data: AndroidActivityBackPressedEventData) => {
this.routerExtensions.back();
});
I am unable to return to the previous component.
How would I achieve that?
Try to overwrite the default Android behavior for the back pressed event as shown in this StackOverflow answer
Notice the data.cancel is set to true
application.android.on(AndroidApplication.activityBackPressedEvent, (data: AndroidActivityBackPressedEventData) => {
data.cancel = true; // prevents default back button behavior
});

Why won't VueJS invoke methods from the created() function?

Learning VueJS and trying to do a simple API call on component load to put a list of repos onto my page. When I call and set the this.repos from the created() method, no problem. But if I set it as a method and then call it from this.getRepos nothing happens. No error, nothing. What am I missing about VueJS?
This works:
data: () => ({
msg: 'Github Repos',
ok: 'Im practically giving away these repos',
repos: [],
}),
methods: {
},
async created() {
const repos = await axios.get('https://api.github.com/orgs/octokit/repos');
this.repos = repos.data.map(repo =>
`<div class="box"><a href="${repo.html_url}">
${repo.name}
</div>`,
);
},
This DOES NOT work:
data: () => ({
msg: 'Github Repos',
ok: 'Im practically giving away these repos',
repos: [],
}),
methods: {
getRepos: async () => {
const repos = await axios.get('https://api.github.com/orgs/octokit/repos');
this.repos = repos.data.map(repo =>
`<div class="box"><a href="${repo.html_url}">
${repo.name}
</div>`,
);
},
},
created() {
this.getRepos();
},
Any ideas? Thanks!
It's simply because you used arrow functions here so that this.repos's this is bound to window object. Changing async () => {} to async function() {} will help you overcome it.
See demo
Note that you should not use an arrow function to define a method (e.g. plus: () => this.a++). The reason is arrow functions bind the parent context, so this will not be the Vue instance as you expect and this.a will be undefined.
reference
Another way to do an Axios call with Vue using then() method:
demo
created() {
axios.get('https://api.github.com/orgs/octokit/repos', {
params: {
type: 'all',
},
})
.then((res) => {
console.log('Success Response', res.data);
res.data.forEach((repo) => {
this.repos.push({ name: repo.name, url: repo.html_url, language: repo.language });
});
})
.catch((err) => {
console.log('Error', err);
});
},

Resources