In my application, I have the following code.
case ADD_MOVEMENT:
let am_selectedTrainerMovements = state.selectedTrainerMovements;
state.trainerMovements.forEach(movement => {
if (movement.id === action.movement.id) {
am_selectedTrainerMovements.push(movement);
}
});
return {
...state,
selectedTrainerMovements: am_selectedTrainerMovements
};
break;
In the reducer I use this case. But this gives me an error saying "the push method cannot be invoked on immutable data structure"
What am I doing wrong here?
You set am_selectedTrainerMovements equal to state.selectedTrainerMovements and so you are just creating a new pointer to the exact same object. So when you call am_selectedTrainerMovements.push to are trying to change the state which is immutable.
You you need to clone state.selectedTrainerMovements, for instance:
let am_selectedTrainerMovements =
Object.assign({}, state. state.selectedTrainerMovements);
Related
I am looking for a way to overwrite expect method for TestController. My idea is existing tests whoever used t.expect method, I want to perform additional steps in those cases.
I came up with below sample code but testcafe runtime fails with below error
TypeError: Cannot read property '_expect$' of undefined
sample code attempting to override:
import { Selector } from "testcafe";
fixture`Getting Started`.page`http://devexpress.github.io/testcafe/example`;
test("My first test", async (t) => {
t = modify(t);
await t.typeText("#developer-name", "John Smith").click("#submit-button");
// Use the assertion to check if the actual header text is equal to the expected one
await t
.expect(Selector("#article-header").innerText)
.eql("Thank you, John Smith!");
});
function modify(t) {
let prevExpect = t.expect;
t.expect = (param) => {
console.log("modified expecte has been used");
return prevExpect(param);
};
return t;
}
Also, when using t.click(Selector(...).expect(...), It doesn't use my overwritten expect. How to make it work in the call chain as well?
Technically, it's possible to overwrite the expect method, but please note that this approach may lead to incorrect work and unexpected errors.
You need to modify your modify function as follows:
function modify (t) {
let prevExpect = t.expect;
t.expect = (param) => {
console.log("modified expect has been used");
return prevExpect.call(t, param);
};
return t;
}
As for the t.click(Selector(...).expect(...) issue, you call the expect method of Selector, but Selector does not have the expect method.
You need to add ) after Selector:
await t.click(Selector(...)).expect(...)
Eventually, I would like to be able to run background tasks in my React Native app (Axios fetch to get some fresh data at least once a day). I am struggling to make this work:
https://docs.expo.io/versions/latest/sdk/task-manager/
import * as BackgroundFetch from 'expo-background-fetch';
import * as TaskManager from 'expo-task-manager';
const FETCH_TASKNAME = 'test_task'
const INTERVAL = 60
function test() {
console.log('function is running')
}
export async function registerFetchTask() {
TaskManager.defineTask(FETCH_TASKNAME, test());
const status = await BackgroundFetch.getStatusAsync();
switch (status) {
case BackgroundFetch.Status.Restricted:
case BackgroundFetch.Status.Denied:
console.log("Background execution is disabled");
return;
default: {
console.debug("Background execution allowed");
let tasks = await TaskManager.getRegisteredTasksAsync();
if (tasks.find(f => f.taskName === FETCH_TASKNAME) == null) {
console.log("Registering task");
await BackgroundFetch.registerTaskAsync(FETCH_TASKNAME);
tasks = await TaskManager.getRegisteredTasksAsync();
console.debug("Registered tasks", tasks);
} else {
console.log(`Task ${FETCH_TASKNAME} already registered, skipping`);
}
console.log("Setting interval to", INTERVAL);
await BackgroundFetch.setMinimumIntervalAsync(INTERVAL);
}
}
}
and calling this in App.js
import { registerFetchTask } from './helpers/backgroundFetch'
registerFetchTask();
I am getting a console logs up to this point:
function is running
Background execution allowed
Registering task
But I am unfortunately also getting following errors:
TaskManager.defineTask must be called during the initialization phase!
I read also in the documentation and as per example code, I am running in App.js directly and not in the component class.
And I am getting the following warning:
[Unhandled promise rejection: Error: Task 'test_task' is not defined. You must define a task using TaskManager.defineTask before registering.]
Which I don't understand since it is defined at the very top and before registering.
It is only unfortunate there is no proper working example anywhere to be found. An example would save countless hours for people struggling with this. Is there maybe an easier way of making background tasks running in react native apps?
Thanks so much for your kind help.
I can spot a couple of problems:
When you define the task, pass in a reference to the function rather than calling it:
TaskManager.defineTask(FETCH_TASKNAME, test); // no parentheses
registerFetchTask() is async which means it returns a promise when called in App.js. That probably doesn't count as the "initialization phase" of the app so try removing async
I don't know whether these changes will solve the problem but they should help.
change the line TaskManager.defineTask(FETCH_TASKNAME, test()); to
TaskManager.defineTask(FETCH_TASKNAME, test);
instead of passing the return value of the function pass the function reference.
In VueJS I have a vuex store getter which may throw an error of type ErrorOne or ErrorTwo.
// myGetter.js
export class ErrorOne extends Error {}
export class ErrorTwo extends Error {}
export default () => {
if (...) {
throw new ErrorOne()
}
if (...) {
throw new ErrorTwo()
}
return ...
}
And in a computed property in my Vue component I am using this getter but I want to handle these errors in a try catch block.
// MyComponent.vue
import { ErrorOne, ErrorTwo } from '.../myGetter'
export default {
...,
data() {
return {
errorOne: false,
errorTwo: false
}
},
computed: {
myGetterComputed() {
try {
const value = this.$store.getters['.../myGetter']
this.errorOne = false // Unexpected side effect
this.errorTwo = false // Unexpected side effect
return value
} catch (err) {
switch (err.constructor) {
case ErrorOne:
this.errorOne = true // Unexpected side effect
break
case ErrorTwo:
this.errorTwo = true // Unexpected side effect
break
}
}
}
}
}
But eslint tells me [eslint] Unexpected side effect in "myComputedGetter" computed property. [vue/no-side-effects-in-computed-properties].
What is the correct way to handle errors in Vue computed properties in my use case?
Should I move myGetterComputed to data and use a watch method to handle updates?
If I am going straight to answer your question I can tell you that eslint is using this rule to warn you about an unintended side effect. As per the eslint-plugin-vue docs
It is considered a very bad practice to introduce side effects inside computed properties. It makes the code not predictable and hard to understand.
Basically what we need to remember is that computed properties are meant to be used when there's heavy logic associated to how we treat data inside templates. So you shouldn't be updating any properties/data inside a computed property logic.
I would like to help you further if you provide a more detailed example of what you're trying yo achieve
What is the difference between returning an action vs returning the whole function in Page Object?
this.download = function() {
element(by.id('modal-download-button')).click();
return this;
};
VS
this.download = function() {
return element(by.id('modal-download-button')).click();
};
Sometimes, to tackle timing and syncing issues, you want to explicitly resolve a promise returned by click(). In this case returning the "click" promise makes sense:
pageObject.download().then(function () {
// ...
});
Returning a full page object could be useful for chaining page object methods:
pageObject.download().get().verify();
For some reason, my code is unable to retrieve the IAsyncOperation object that is returned upon calling captureFileAsync method of the Windows.Media.Capture.CameraCaptureUI() method. The IAsyncOperation object is returned according to this documentation. In that documentation link, it states:
Return value
Type: IAsyncOperation<StorageFile>
When this operationcompletes, a StorageFile object is returned.
So here is my code:
var dialog = new Windows.Media.Capture.CameraCaptureUI();
var aspectRatio = { width: 4, height: 3 };
dialog.photoSettings.croppedAspectRatio = aspectRatio;
appSession.InAsyncMode = dialog.captureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.photo).done(function (file) {
if (file) {
self.addPage(URL.createObjectURL(file));
} else {
WinJS.log && WinJS.log("No photo captured.", "sample", "status");
}
}, function (err) {
// None taken
});
When I inspect the value of appSession.InAysncMode, I see that the function returns undefined. I suspect it returns undefined because the operation is not complete (i.e. the user has not yet created the photo, and it has not been saved to disc), but I need it in order to cancel out of the camera capture mode programmatically. Does anybody know why it would return undefined instead of the documented IAsyncOperation object?
Thanks!
For reference, here's the answer I posted on the MSDN forum.
To answer your ending question, you can cancel the capture UI by canceling the promise from dialog.captureFileAsync.
Your InAsyncMode flag is undefined because you're assigning to it the return value from captureFileAsync.done() which is, by definition, undefined. It has nothing to do with the API's success.
In the docs, when you see IAsyncOperation, what you get in JavaScript is a promise that will deliver as a result to the completed handler if it succeed. You never see IAsyncOperation or related interfaces in JavaScript directly. The documentation for WinRT is written to be language-neutral, so it's important to understand how those things show up in JS (as promises). In C# you don't see it either, as you just use the await keyword. It's mostly in C++ that you actually encounter the interface.
Anyway, you I believe you want is something along the lines of the code below, where you could eliminate IsAsyncMode in favor of just checking for a non-null promise:
appSession.capturePromise = dialog.captureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.photo);
appSession.IsAsyncMode = (appSession.capturePromise != null);
//This will close the capture UI after 5 seconds--replace with whatever logic you need
setTimeout(function () { appSession.capturePromise.cancel(); }, 5000);
appSession.capturePromise.done(function (file) {
if (file) {
} else {
}
}, function (err) {
appSession.IsAsyncMode = false;
appSession.capturePromise = null;
});