Here is my code :
let namesList = ref([]);
const GetFormData = (payload) => {
return new Promise((resolve, reject) => {
api
.get("api.php", { params: { search: payload } })
.then((response) => {
data.value = response.data;
// console.log(data.value);
// convert array objects to array strings
namesList = data.value.map(function (list) {
return list["first_name"];
});
// console.log(namesList);
})
.catch((error) => {
reject(error);
});
});
};
If I console the namelist inside the function it returns the value :
(9) ['Michael Angelodfsed', 'Mardin', 'Joemar', 'Chirs', 'chan', 'loys', 'Lorena', 'kayabusa', 'kayabusa']
0: "Michael Angelodfsed"
1: "Mardin"
2: "Joemar"
3: "Chirs"
4: "chan"
5: "loys"
6: "Lorena"
7: "kayabusa"
8: "kayabusa"
length: 9
[[Prototype]]: Array(0)
but if I console the variable outside the function it gives me this console.log(nameList);
RefImpl {__v_isShallow: false, dep: undefined, __v_isRef: true, _rawValue: Array(0), _value: Proxy}
dep: Set(1) {ReactiveEffect}
__v_isRef: true
__v_isShallow: false
_rawValue: []
_value: Proxy
[[Handler]]: Object
[[Target]]: Array(0)
[[IsRevoked]]: false
value: (...)
[[Prototype]]: Object
please help me guys. really struggling here. really appreciate your help.
Follow this:
consf nameList = ref([])
console.log(nameList.value) // get value
nameList.value = ["Shin"] // set value
As #Deepak stated, you are trying to access the variable before the function (the api call) ends.
Your namesList is a ref object, so when you log it before it ends, it logs the object.
As your function is calling an api and use a Promise, you can change your function code to this:
const GetFormData = (payload) => {
return new Promise((resolve, reject) => {
api
.get("api.php", { params: { search: payload } })
.then((response) => {
data.value = response.data;
// console.log(data.value);
// convert array objects to array strings
namesList = data.value.map(function (list) {
return list["first_name"];
});
// console.log(namesList);
resolve(namesList);
})
.catch((error) => {
reject(error);
});
});
};
GetFormData(payload).then(data => console.log(data))
Related
I am creating MongoDB records based on user inputs, and then for each new object created, I am pushing the object ID into an array. My problem is my console.log statement in the last line returns empty. So How I could wait on the forEach execution to be over so I have the updated assetsArray, any help is appreciated!
Here is my code:
let assetsArray = [];
if (assets) {
JSON.parse(assets).forEach(asset => {
Image.create({
organization: organizationID,
imageName: asset.imageName,
imageDescription: asset.imageDescription ?? null,
imagePath: asset.imagePath
}).then(record => {
console.log(record)
assetsArray.push(record._id)
})
})
}
console.log(assetsArray)
You can use Promise.all for your case
const tasks = JSON.parse(assets).map(asset => {
return Image.create({
organization: organizationID,
imageName: asset.imageName,
imageDescription: asset.imageDescription ?? null,
imagePath: asset.imagePath,
})
});
Promise.all(tasks).then((records) => {
return records.map(record => {
console.log(record)
return record._id
})
}).then(assetsArray => {
console.log(assetsArray)
})
The response for an api call is like so:
//Calling the api
useEffect(() => {
runFunction(params, someMoreParams);
});
async function setDeliveryOptions(cartItems, checkoutState) {
const response = await authFetch({
url: `apiURL`,
method: 'POST',
body: JSON.stringify(orderBody),
});
const jsonResponse = await response.json();
console.log(jsonResponse);
const deliveries = jsonResponse.deliveries.map(
(items) => items.scheduleOptions,
);
const jsonResponse = await response.json();
console.log(jsonResponse);
//RESPONSE:
deliveries: Array(1).
0: items: (2) [{…}, {…}]
options: 0: //THIS IS THE DATA I WANT
end: "2022-09-01T15:15:00Z"
price:55
price_ex_vat: 44
start: "2022-09-01T15:15:00Z"
type: "POSTAL"
[[Prototype]]: Object
supplier: "supplier"
[[Prototype]]: Object
length: 1
[[Prototype]]: Array(0)
const data = jsonResponse.options.map(
(items) => items.options,
);
// trying to save data:
const type = data.map((items) => items);
const start = data[0].map((items) => items.start);
const end = data[0].map((items) => items.end);
const price = data[0].map((items) => items.price);
console.log('deliveries', data);
console.log('type', type);
console.log('start', start);
console.log('end', end);
console.log('price', price);
}
how do i get the data and save it to a variable. this is run on react, and is called when website is rendered. This code saves the data to the variables but i get a react error stating that values are undefined. maybe it is a react thing?
thanks for any help
I have API query and getting the result and setting those in a state variable in Oncompleted method of API query, Now i am updating the same state variable in another api query "onCompleted method.
I am not able to access the result from state what i have set before in first api query and below is my code
Query 1:
const designHubQueryOnCompleted = designHubProject => {
if (designHubProject) {
const {
name,
spaceTypes
} = designHubProject;
updateState(draft => { // setting state here
draft.projectName = name;
draft.spaceTypes = (spaceTypes || []).map(po => {
const obj = getTargetObject(po);
return {
id: po.id,
name: obj.name,
category: obj.librarySpaceTypeCategory?.name,
description: obj.description,
warning: null // trying to modify this variable result in another query
};
});
});
}
};
const { projectDataLoading, projectDataError } = useProjectDataQuery(
projectNumber,
DESIGNHUB_PROJECT_SPACE_TYPES_MIN,
({ designHubProjects }) => designHubQueryOnCompleted(designHubProjects[0])
);
Query 2:
const {
// data: designhubProjectSpaceTypeWarnings,
loading: designhubProjectSpaceTypeWarningsLoading,
error: designhubProjectSpaceTypeWarningsError
} = useQuery(DESIGNHUB_PROJECT_LINKED_SPACETYPE_WARNINGS, {
variables: {
where: {
projectNumber: { eq: projectNumber }
}
},
onCompleted: data => {
const projectSpaceTypeWarnings = data.designHubProjectLinkedSpaceTypeWarnings[0];
const warnings = projectSpaceTypeWarnings.spaceTypeWarnings.reduce((acc, item) => {
const spaceTypeIdWithWarningState = {
spaceTypeId: item.spaceTypeProjectObjectId,
isInWarningState: item.isInWarningState
};
acc.push(spaceTypeIdWithWarningState);
return acc;
}, []);
console.log(state.spaceTypes); // trying to access the state here but getting empty array
if (state.spaceTypes.length > 0) {
const updatedSpaceTypes = state.spaceTypes;
updatedSpaceTypes.forEach(item => {
const spaceTypeWarning = { ...item };
spaceTypeWarning.warning = warnings?.filter(
w => w.spaceTypeId === spaceTypeWarning.id
).isInWarningState;
return spaceTypeWarning;
});
updateState(draft => {
draft.spaceTypes = updatedSpaceTypes;
});
}
}
});
Could any one please let me know where I am doing wrong with above code Or any other approach to modify the state, Many thanks in advance!!
I am little confused on why an array is not updating when I resolve a promise that contains Firestore nested get.
The code is below:
let userArray = [];
return new Promise(resolve => {
channelPaticipationRef
.where('channel', '==', channel.id)
.get()
.then(participationSnapshot => {
participationSnapshot.forEach(participationDoc => {
const participation = participationDoc.data();
participation.id = participationDoc.id;
if (participation.user != userId) {
usersRef
.doc(participation.user)
.get()
.then(user => {
if (user.data()) {
const userData = user.data();
userArray = [
...userArray,
{
userId: userData.id,
userFirstName: userData.firstName,
userLastName: userData.lastName,
userIsOnline: userData.isOnline,
userProfilePictureURL: userData.profilePictureURL,
userLastTimestamp: userData.lastOnlineTimestamp,
},
];
console.log(1, userArray)
}
})
.catch(error => console.log(error));
}
console.log(2, userArray)
});
console.log(3, userArray)
resolve(userArray);
});
});
In the console it returns
2 []
2 []
3 []
1 [{…}]
1 (2) [{…}, {…}]
and the promise returns an empty array
If I am pushing or updating the array using a spread operator, why is it not registering?
I've got following Epic which works well in application, but I can't get my marble test working. I am calling action creator in map and it does return correct object into stream, but in the test I am getting empty stream back.
export const updateRemoteFieldEpic = action$ =>
action$.pipe(
ofType(UPDATE_REMOTE_FIELD),
filter(({ payload: { update = true } }) => update),
mergeMap(({ payload }) => {
const { orderId, fields } = payload;
const requiredFieldIds = [4, 12]; // 4 = Name, 12 = Client-lookup
const requestData = {
id: orderId,
customFields: fields
.map(field => {
return (!field.value && !requiredFieldIds.includes(field.id)) ||
field.value
? field
: null;
})
.filter(Boolean)
};
if (requestData.customFields.length > 0) {
return from(axios.post(`/customfields/${orderId}`, requestData)).pipe(
map(() => queueAlert("Draft Saved")),
catchError(err => {
const errorMessage =
err.response &&
err.response.data &&
err.response.data.validationResult
? err.response.data.validationResult[0]
: undefined;
return of(queueAlert(errorMessage));
})
);
}
return of();
})
);
On successfull response from server I am calling queueAlert action creator.
export const queueAlert = (
message,
position = {
vertical: "bottom",
horizontal: "center"
}
) => ({
type: QUEUE_ALERT,
payload: {
key: uniqueId(),
open: true,
message,
position
}
});
and here is my test case
describe("updateRemoteFieldEpic", () => {
const sandbox = sinon.createSandbox();
let scheduler;
beforeEach(() => {
scheduler = new TestScheduler((actual, expected) => {
expect(actual).toEqual(expected);
});
});
afterEach(() => {
sandbox.restore();
});
it("should return success message", () => {
scheduler.run(ts => {
const inputM = "--a--";
const outputM = "--b--";
const values = {
a: updateRemoteField({
orderId: 1,
fields: [{ value: "test string", id: 20 }],
update: true
}),
b: queueAlert("Draft Saved")
};
const source = ActionsObservable.from(ts.cold(inputM, values));
const actual = updateRemoteFieldEpic(source);
const axiosStub = sandbox
.stub(axios, "post")
.returns([]);
ts.expectObservable(actual).toBe(outputM, values);
ts.flush();
expect(axiosStub.called).toBe(true);
});
});
});
output stream in actual returns empty array
I tried to return from map observable of the action creator which crashed application because action expected object.
By stubbing axios.post(...) as [], you get from([]) in the epic - an empty observable that doesn't emit any values. That's why your mergeMap is never called. You can fix this by using a single-element array as stubbed value instead, e.g. [null] or [{}].
The below is an answer to a previous version of the question. I kept it for reference, and because I think the content is useful for those who attempt to mock promise-returning functions in epic tests.
I think your problem is the from(axios.post(...)) in your epic. Axios returns a promise, and the RxJS TestScheduler has no way of making that synchronous, so expectObservable will not work as intended.
The way I usually address this is to create a simple wrapper module that does Promise-to-Observable conversion. In your case, it could look like this:
// api.js
import axios from 'axios';
import { map } from 'rxjs/operators';
export function post(path, data) {
return from(axios.post(path, options));
}
Once you have this wrapper, you can mock the function to return a constant Observable, taking promises completely out of the picture. If you do this with Jest, you can mock the module directly:
import * as api from '../api.js';
jest.mock('../api.js');
// In the test:
api.post.mockReturnValue(of(/* the response */));
Otherwise, you can also use redux-observable's dependency injection mechanism to inject the API module. Your epic would then receive it as third argument:
export const updateRemoteFieldEpic = (action$, state, { api }) =>
action$.pipe(
ofType(UPDATE_REMOTE_FIELD),
filter(({ payload: { update = true } }) => update),
mergeMap(({ payload }) => {
// ...
return api.post(...).pipe(...);
})
);
In your test, you would then just passed a mocked api object.