I used aws-sns to create one webhook. Two lambda functions are checked by this webhook. One of the lambda functions publishes 'orderId' and'startTime', while another publishes 'orderId' and 'roundName'. Both lambdas fire at different times. As a result, publishing can happen at two different times. One or both of the'startTime' and 'roundName' parameters may be undefined.
If 'roundName' exists, the 'updateOrder' variable will return 'roundName,' and the database will be updated. When'startTime' is set and 'roundName' is left blank, the 'roundName' will be rewritten from the database, which I don't want. Because if there is a 'roundName,' there will always be a 'roundName,' the value of 'roundName' can change but it will never be undefined.If startTime changes as well as roundName change then it will update the database. But my current logic is wrong. Struggling to implementing diffrent scenario logic.
const data = {
Records: [
{
Sns: {
Message:
'[{\n "orderId": "a4013438-926f-4fdc-8f6a-a7aa402b40ea",\n "roundName": "RO1"}]',
},
},
],
};
const existingData = [
{
modifiedAt: "2022-03-09T13:18:06.211Z",
lastMile: "progress",
createdAt: "2022-02-26T06:38:50.967+00:00",
orderId: "a4013438-926f-4fdc-8f6a-a7aa402b40ea",
},
];
// parse the data
const parseData = data.Records.flatMap((record) =>
JSON.parse(record.Sns.Message)
);
// check if the data exist or not
const existingOrder = existingData.filter(
(o1) => parseData.some((o2) => o1.orderId === o2.orderId)
);
// if there is no existingOrder then return false
if (existingOrder.length === 0) return;
// if there is exisiting order then add roundName and startTime from SNS event
const updateOrder = existingOrder.map((i) => {
const roundName = parseData.find((r) => {
return r.orderId === i.orderId;
}).roundName;
const startTime = parseData.find((r) => {
return r.orderId === i.orderId;
}).startTime;
return {
roundName: roundName ?? "",
startTime: startTime ?? "",
};
});
console.log(updateOrder);
Related
im fetching data from APi and doing filtering from severside, i'm using useInfiniteScroll to fetch only limited amount of data on the first page, and with this im doing pagination too...
const [casesList, setCasesList] = useState<CaseModel[]>([]);
const [isLoading, setIsLoading] = useState<boolean>(false);
const [isFetchingData, setIsFetchingData] = useState<boolean>(true);
const { inputValue } = React.useContext(MenuContext);
const debouncedValue = useDebounce(inputValue, 10);
these are my hook, (casesList) in which im saving all my incoming data from APi, input value is the value that im typing in search box for filtering the data, and debouncedValue is my custom hook, so the inputValue first goes to debouncedValue and then my debouncedValue will get the value of my inputValue,
const [pagination, setPagination] = useState<Pagination>({
continuationToken: "",
hasMoreResults: true,
});
const [isFetchingMore, setIsFetchingMore] = useInfiniteScroll();
these are my pagination and useInfiniteScroll() hooks...
so the actual problem that i'm facing is that,
const getDashboardCases = useCallback(
async (continuationToken: string) => {
setIsLoading(true);
let casesPageLimit = CASES_PAGE_LIMIT;
if (casesList.length === 0) {
const table = document.querySelector("#cases-items");
if (table) {
const caseItemHeight = 80;
const heightDifference =
table?.getBoundingClientRect().y > 0
? window.innerHeight - table?.getBoundingClientRect().y
: -1;
casesPageLimit = Math.max(
casesPageLimit,
Math.ceil(heightDifference / caseItemHeight)
);
}
}
const options: GetCasesListOptions = {
continuationToken,
filter: [],
sort: [],
pageLimit: casesPageLimit,
search: [debouncedValue]
};
const data: IData = await dashboardService.getCasesList(options);
setIsFetchingMore(false);
setIsLoading(false);
if (data.result) {
setIsFetchingData(false)
if (data.continuationToken !== undefined) {
const newContinuationToken = data.continuationToken;
setPagination((prevPagination) => ({
...prevPagination,
hasMoreResults: data.hasMoreResults,
continuationToken: newContinuationToken,
}));
} else {
setPagination((prevPagination) => ({
...prevPagination,
hasMoreResults: false,
}));
}
setCasesList((prevCases) => [...prevCases, ...data.result]);
dispatch(setAllowedClassifications(data.options));
}
},
[casesList.length, dashboardService, debouncedValue]
);
this code is fetching the data from the APi and for filtering i created an Object name Options
const options: GetCasesListOptions = {
continuationToken,
filter: [],
sort: [],
pageLimit: casesPageLimit,
search: [debouncedValue]
};
im saving my debouncedValue to the search Array in the Options object and then im using Options object in APi to filter the data
const data: IData = await dashboardService.getCasesList(options);
for example if i have 15 objects in APi, i need to get first 10 objects, and then i scroll down my callback function executes one more time and get the rest of the data...
if (data.result) {
setIsFetchingData(false)
if (data.continuationToken !== undefined) {
const newContinuationToken = data.continuationToken;
setPagination((prevPagination) => ({
...prevPagination,
hasMoreResults: data.hasMoreResults,
continuationToken: newContinuationToken,
}));
} else {
setPagination((prevPagination) => ({
...prevPagination,
hasMoreResults: false,
}));
}
setCasesList((prevCases) => [...prevCases, ...data.result]);
dispatch(setAllowedClassifications(data.options));
}
it's already done there...
now i want that, if i type something in the search box my api should run again to add my search value in the APi and filters the data...
but i'm facing problems doing this...
im calling my usecallback function like this...
useEffect(() => {
if (isFetchingMore && pagination.hasMoreResults) {
getDashboardCases(pagination.continuationToken);
}
}, [
getDashboardCases,
isFetchingMore,
pagination.continuationToken,
pagination.hasMoreResults,
debouncedValue
]);
if isFetchingMore && pagination.hasMoreResults is true, then it executes the function, but if type something in searchbox it is not running my function again...
i also tried to remove the if condition in the useEffect but it started infinite scrolling making duplicates of data, and i get this error...
Encountered two children with the same key, `d77c39f2-2dcd-4c4e-b7ee-1fde07b6583f`. Keys should be unique so that components maintain their identity across updates
so i need to re-run the function if i type something in search box and not get duplicated data back, and also i want to run the if condition that i typed in the useEffect...
please help, Thank you :)
I'm trying to clean up the data received from firebase to view them in a FlatList. How can I clean my data to a simple array where I can iterate in FlatList?
EDIT! There are many other coins in my database that I want to pull into the FlatList. So the solution that I'm looking for is to view all these coins in my FlatList and then show their data such as price, market_cap etc.
My data is currently stored in a state and looks like this.
favoriteList data is:
Object {
"bitcoin": Object {
"-MahI1hCDr0CJ_1T_umy": Object {
"data": Object {
"ath": 54205,
"ath_change_percentage": -40.72194,
"ath_date": "2021-04-14T11:54:46.763Z",
"atl": 51.3,
"atl_change_percentage": 62536.71794,
"atl_date": "2013-07-05T00:00:00.000Z",
"circulating_supply": 18719656,
"current_price": 32164,
"fully_diluted_valuation": 674764316483,
"high_24h": 33004,
"id": "bitcoin",
"image": "https://assets.coingecko.com/coins/images/1/large/bitcoin.png?1547033579",
"last_updated": "2021-05-27T10:07:02.525Z",
"low_24h": 30652,
"market_cap": 601493137412,
"market_cap_change_24h": -15118857257.119507,
"market_cap_change_percentage_24h": -2.45192,
"market_cap_rank": 1,
"max_supply": 21000000,
"name": "Bitcoin",
"price_change_24h": -641.85835686,
"price_change_percentage_1h_in_currency": 0.25769270475453127,
"price_change_percentage_24h": -1.95655,
"price_change_percentage_24h_in_currency": -1.9565521832416402,
"price_change_percentage_7d_in_currency": 4.978932125496787,
"symbol": "btc",
"total_supply": 21000000,
"total_volume": 36947814578,
},
},
},
}
The firebase structure is like this where the data above is fetched from:
Object.keys(favourite.bitcoin)[idx] This line gives you the name of key at index 0 into object favourite.bitcoin.
So the variable key will be your firebase key.
let favourite = {
bitcoin: {
"-MahI1hCDr0CJ_1T_umy": {
data: {
ath: 54205,
ath_change_percentage: -40.72194,
ath_date: "2021-04-14T11:54:46.763Z",
atl: 51.3,
atl_change_percentage: 62536.71794,
atl_date: "2013-07-05T00:00:00.000Z",
circulating_supply: 18719656,
current_price: 32164,
fully_diluted_valuation: 674764316483,
high_24h: 33004,
id: "bitcoin",
image:
"https://assets.coingecko.com/coins/images/1/large/bitcoin.png?1547033579",
last_updated: "2021-05-27T10:07:02.525Z",
low_24h: 30652,
market_cap: 601493137412,
market_cap_change_24h: -15118857257.119507,
market_cap_change_percentage_24h: -2.45192,
market_cap_rank: 1,
max_supply: 21000000,
name: "Bitcoin",
price_change_24h: -641.85835686,
price_change_percentage_1h_in_currency: 0.25769270475453127,
price_change_percentage_24h: -1.95655,
price_change_percentage_24h_in_currency: -1.9565521832416402,
price_change_percentage_7d_in_currency: 4.978932125496787,
symbol: "btc",
total_supply: 21000000,
total_volume: 36947814578,
},
},
},
};
let idx = 0; //key at index 0
let key = Object.keys(favourite.bitcoin)[idx];
console.log(key)
let data = favourite.bitcoin[key].data;
console.log(data)
Please let me know if it's works or not !
To get the data from your database, you need to query its parent reference. This will allow you to do things like "find all entries under /favorites/bitcoin that have a current price of over 30000".
Because you want to simply query for all the data under /favorites/bitcoin in your question, you would do the following:
Get a reference for /favorites/bitcoin
Get the data under /favorites/bitcoin
Iterate over the data, and assemble an array
Use this new array for your FlatList
These steps can be made into the following function:
function getDataForFlatlistUnder(databasePath) {
return firebase.database()
.ref(databasePath)
// consider using .limitToFirst(10) or similar queries
.once("value")
.then((listSnapshot) => {
// listSnapshot contains all the data under `${databasePath}`
const arrayOfDataObjects = [];
// For each entry under `listSnapshot`, pull its data into the array
// Note: this is a DataSnapshot#forEach() NOT Array#forEach()
listSnapshot.forEach((entrySnapshot) => {
// entrySnapshot contains all the data under `${databasePath}/${entrySnapshot.key}`
const data = entrySnapshot.child("data").val();
// data is your data object
// i.e. { ath, ath_change_percentage, ath_date, atl, ... }
// add the key into the data for use with the FlatList
data._key = entrySnapshot.key;
arrayOfDataObjects.push(data);
});
return arrayOfDataObjects;
});
}
Which you can use in your component like so:
function renderItem((dataObject) => {
// TODO: render data in dataObject
});
function MyComponent() {
const [listData, setListData] = useState();
const [listDataError, setListDataError] = useState(null);
const [listDataLoading, setListDataLoading] = useState(true);
useEffect(() => {
const disposed = false;
getDataForFlatlistUnder("favorites/bitcoin")
.then((arrayOfDataObjects) => {
if (disposed) return; // component was removed already, do nothing
setListData(arrayOfDataObjects);
setListDataLoading(false);
})
.catch((err) => {
if (disposed) return; // component was removed already, do nothing
// optionally empty data: setListData([]);
setListDataError(err);
setListDataLoading(false);
});
// return a cleanup function to prevent the callbacks above
// trying to update the state of a dead component
return () => disposed = true;
}, []); // <-- run this code once when component is mounted and dispose when unmounted
if (listDataLoading)
return null; // or show loading spinner/throbber/etc
if (listDataError !== null) {
return (
<Text>
{"Error: " + listDataError.message}
</Text>
);
}
return (
<FlatList
data={listData}
renderItem={renderItem}
keyExtractor={item => item._key} // use the key we inserted earlier
/>
);
}
Note: This code is for a one-off grab of the data, if you want realtime updates, you would modify it to use .on("value", callback) instead. Make sure to use .off("value", callback) in the unsubscribe function of the useEffect call to clean it up properly.
It is interesting to see how programmers interpret questions. Or perhaps how beginners fail to articulate clearly what they want to achieve. Here is the answer:
const formatData = (data) => {
let arr = [];
let test = Object.values(data).forEach((o) => {
Object.values(o).forEach((a) =>
Object.values(a).forEach((b) => arr.push(b))
);
setFormattedData(arr);
});
Given the following script:
type Data = {
id: string
value: number
}
// This is a pure function: given val, res will always be the same
const veryExpensiveCalc = (val: number) => {
const res = // ... 5 seconds of sync computation ...
return res
}
const array$ = new ReplaySubject<Array<Data>>(1)
const allComputedValues$ = array$.pipe(
map(arr =>
arr.map(item =>
// I want this veryExpensiveCalc to be performed only when
// item.value changes for this item.id, or the item was not
// there before
veryExpensiveCalc(item.value)
)
)
)
allComputedValues$
.pipe(
tap(newStruct => {
console.log('newStruct', newStruct)
})
)
.subscribe()
I'd like to optimize how allComputedValues$ is calculated. In particular let's say that an item is added or removed to array$, or the order of the elements change: then veryExpensiveCalc is executed again on every item of the array, even though that's not needed at all. I just need allComputedValues$ from the previous computation with the result of veryExpensiveCalc applied only to the newly added element (in case of addition).
What's the best way to write this in a functional reactive fashion? It should work also if there are multiple elements edited/added/removed at the same time (so that veryExpensiveCalc is executed only on the elements that have a different value given the same id).
I think you can use the scan() operator here:
const allComputedValues$ = array$.pipe(
scan(
(acc, crtArr) => {
// with these we 'automatically' remove the current items(from `acc`) whose ids are not in the current array
const newIds = {};
const newValues = {};
crtArr.forEach(crt => {
const { id: currentId, value: crtValue } = crt;
// if new or edited
if (!acc.ids[currentId] || acc.values[currentId] !== crtValue) {
newIds[currentId] = true;
newValues[currentId] = veryExpensiveCalc(crtValue);
}
});
return { ids: newIds, values: newValues };
},
{ ids: {}, values: {} },
),
)
I'm using electron with Vue. I'm saving data using nedb. I'm sending the event to background.js from vue component and when it returns with data it adds data in vuex in fibbonaccicaly.
like
If I add 1 object let's say A then vuex store 1 object
if I add 1 more object let's say B then vuex store has total 3
objects (1 for A and 2 for B); and so on.
So I need to insert data in vuex only one time. How'd I do that ?
// In CreateNewTodo.vue
methods:{
// saveTodo method get triggers when user submit the form in modal
saveTodo() {
if (this.isFormValid) {
const newTodo = {
task: this.task,
priority: this.priority,
eventDate: this.eventDate,
createdDate: new Date(),
completedDate: null,
isCompleted: false,
};
// new Todo is an object that contains data that is requested from user
// from a form like task, priority and eventDate
ipcRenderer.send('createNewTodo', newTodo);
ipcRenderer.on('createNewTodoResponse', (e, newDoc) => {
if (typeof newDoc === 'object') {
this.$store.dispatch('createNewTodo', newDoc);
$('#createNewModal').modal('hide');
} else {
$('#createNewModal').modal('hide');
}
});
}
},
}
// In background.js
ipcMain.on('createNewTodo', (e, args) => {
// db.performTask is a function that insert document/record in nedb.
// I've used nedb-promises. In return we'll get promise.
const dbpromise = db.performTask('todos', 'insert', args);
// newDoc is the newly inserted document, including its _id
dbpromise.then((newDoc) => {
e.sender.send('createNewTodoResponse', newDoc);
})
.catch(() => {
e.sender.send('createNewTodoResponse', 'error');
});
});
// vuex store
const state = {
todos: [],
};
const getters = {
getAllTodos(todosState) {
return todosState.todos;
},
};
const mutations = {
CREATE_NEW_TODO(todosState, todo) {
todosState.todos.push(todo);
},
};
const actions = {
createNewTodo({ commit }, todo) {
commit('CREATE_NEW_TODO', todo);
},
};
Each time you save a todo, you register a new listener for the IPC reply channel. The listeners all stay active and each picks and processes each event. That's not what you want, you want to process each response only once and electron has a method for that :) try this one:
// register a listener to process the response (once)
ipcRenderer.once('createNewTodoResponse', (e, newDoc) => {
if (typeof newDoc === 'object') {
this.$store.dispatch('createNewTodo', newDoc);
$('#createNewModal').modal('hide');
} else {
$('#createNewModal').modal('hide');
}
});
// send the request
ipcRenderer.send('createNewTodo', newTodo);
I have two separate streams that come together in a combineLatest in something like the following:
const programState$ = Rx.Observable.combineLatest(
high$, low$,
(high, low) => {
return program(high, low);
});
This works fine and dandy but I also want to be able to reset both the high$ and the low$ to their initial state and only fire the program once. Those kind of look like the following:
const high$ = initialDataBranchOne$.merge(interactiveHigh$);
const low$ = initialDataBranchTwo$.merge(interactiveLow$);
Both of those come from an initialData stream that is fired fromEvent. While the program runs normally the combineLatest works great. How can I achieve the same result when the initialData fromEvent is fired? Right now the program gets run twice.
We can store the high and low properties in the same object. We can then perform a scan as various events come in to update this state:
// Define your default high/low values
const defaultHighLow = /** **/;
// Different types of updates/actions
const highUpdate$ = high$.map(high => ({ high, type: 'UPDATE HIGH' }));
const lowUpdate$ = low$.map(low => ({ low, type: 'UPDATE LOW' }));
const resetUpdate$ = reset$.map(high => ({ type: 'RESET' }));
// Merge all the different types of actions to single stream
const update$ = Rx.Observable.merge(highUpdate$, lowUpdate$, resetUpdate$);
// Scan over these updates to modify the high/low values
const highLowState$ = update$.scan((state, update) => {
if (update.type === 'UPDATE HIGH') {
return { ...state, high: update.high };
}
if (update.type === 'UPDATE LOW') {
return { ...state, low: update.low };
}
// Return defaultHighLow if reset update is triggered
if (update.type === 'RESET') {
return defaultHighLow;
}
// Return state by default
return state;
}, defaultHighLow).startWith(defaultHighLow);
And finally we can derive the program state as before:
const programState$ = highLowState$.map(hl => program(hl.high, hl.low));