Check LocaleStorage via Unit tests in React - reactjs

I have been trying to mock my localeStorage with that library https://www.npmjs.com/package/jest-localstorage-mock
But it always shows me the next mistake
SyntaxError: Unexpected token u in JSON at position 0
at JSON.parse ()
Here is mine test
it('checks the locale cost element', () => {
const headerCoinCost = 544123.123543;
const KEY = "walletData",
VALUE = '[{"id":"bitcoin","name":"Bitcoin","price":"38953.6908005677844877","amount":"1"}]';
render(<HeaderWallet headerCoinCost={headerCoinCost} onClick={true ? true : false} ></HeaderWallet>);
const userWalletDifferenceElement = screen.getByTestId("user-wallet__different-cost-test");
expect(userWalletDifferenceElement).toBeInTheDocument();
dispatch(action.update(KEY, VALUE));
expect(localStorage.setItem).toHaveBeenLastCalledWith(KEY, VALUE);
expect(localStorage.__STORE__[KEY]).toBe(VALUE);
expect(Object.keys(localStorage.__STORE__).length).toBe(1);
expect(userWalletDifferenceElement).toHaveTextContent(544123.12);
});
component where I get mistake
export const getLocaleCost = () => {
let localCostArr = [];
let sum = 0;
let existingEntries = JSON.parse(localStorage.getItem("walletData"));
if (existingEntries == null) existingEntries = [];
existingEntries.map(el => {
localCostArr.push(el.price * el.amount)
});
for (let i = 0; i < localCostArr.length; i++) {
sum += +localCostArr[i];
};
return sum;
};

Related

How to resolve dependency API in useEffect beside that saga dispatch also using?

I have the address list, where the divisions, city & area data are available. As per API structure, I have to call dependent API like first division is a sole API, then as per selected division API return list of districts, then as per selected district API will return a list of areas.
On new creation, it works fine but when I am trying to update then it doesn't work properly. I am trying to use here useEffect. On the first useEffect call get division data, set the selected division option, and call city API. On the second useEffect match the selected city & call area. But unfortunately from the second useEffect it's not working properly.
useEffect Demo Code
useEffect(() => {
let selectedRegionId = '';
selectedRegionId = props?.address?.region_id;
setDivision(selectedRegionId)
let data = []
for (let i = 0; i < props.division.length; i++) {
let value = {
isSelected: props.division[i].id == selectedRegionId,
title: props.division[i].title,
id: props.division[i].id,
region_code: props.division[i].region_code
}
data.push(value)
}
let final = data.find((p) => selectedRegionId == p.id)
setItem(final)
props.selectDivision(data)
props.callGetCities(data)
}, [])
useEffect(() => {
let selectedCity = '';
let selectedCityTitle = '';
selectedCityTitle = props?.address?.city;
let cityData = []
for (let i = 0; i < props.cities.length; i++) {
let value = {
isSelected: props.cities[i].title === selectedCityTitle,
title: props.cities[i].title,
id: props.cities[i].id,
statesName: props.cities[i].statesName
}
if (selectedCityTitle.length > 0 && props.cities[i].title === selectedCityTitle) {
selectedCity = props.cities[i].id;
}
cityData.push(value)
}
setCity(selectedCity)
let cityFinal = cityData.find((p) => selectedCity == p.id)
setCItem(cityFinal)
props.selectCity(cityData)
props.callGetAreas(cityData)
setSecondNeedFetching(true);
}, [])
useEffect(() => {
let selectedArea = '';
let selectedAreaTitle = '';
selectedAreaTitle = props?.address?.postcode;
console.log('line 183', selectedAreaTitle)
let data = []
for (let i = 0; i < props.areas.length; i++) {
let value = {
isSelected: props.areas[i].title === selectedAreaTitle,
title: props.areas[i].title,
id: props.areas[i].id,
statesName: props.areas[i].statesName,
citiesName: props.areas[i].citiesName
}
if (selectedAreaTitle.length > 0 && props.areas[i].title === selectedAreaTitle) {
selectedArea = props.areas[i].id;
}
data.push(value)
}
setArea(selectedArea)
let final = data.find((p) => selectedArea == p.id)
setAItem(final)
props.selectArea(data)
}, [])
Anoter Note: On redux store only city value is stored not area cause city useEffect doesn't work
I have tried as per React useEffect hook dependent on a second effect
Also, use the dependent state by adding the following pattern
const [needFetching, setNeedFetching] = useState(false);
const [secondNeedFetching, setSecondNeedFetching] = useState(false);

Data is dissapearing eventhough it is there at the same time

anybody know why the data exists in line 267 but not in 268? Any help is appreciated , thank you.
code
console
full function with useEffect watching props value to trigger the function
function createData() {
//loop through employees and create obj array
const emptyArray = [];
let counter = 0;
if (props.employees) {
const rowData = props.employees.map((item) => {
console.log(item.tests_taken);
let objectDetails = {
firstName: item.first_name,
lastName: item.last_name
};
console.log(item);
console.log(item.tests_taken[0]);
if (item.tests_taken[0]) {
console.log(item.tests_taken[0]);
item.tests_taken[0].forEach((test) => {
console.log(test[Object.keys(test)[0]]);
console.log('yo');
objectDetails = {
...objectDetails,
id: counter,
cefrLevel: test[Object.keys(test)[0]].overallScore.level,
cefrDescription:
test[Object.keys(test)[0]].overallScore.description,
overallScore: test[Object.keys(test)[0]].overallScore.score + '%',
assessmentDate: test[Object.keys(test)[0]].date
};
counter += 1;
emptyArray.push(objectDetails);
});
//console.log(emptyArray);
return objectDetails;
}
props.setEmployees(null);
});
setUsersArray(emptyArray);
console.log(usersArray);
return rowData;
}
}
useEffect(() => {
createData();
}, [props.employees]);

react list rendering failed

environment:react 17.x、umi 3.5.21
In this code below, I send a request and build an array of components, using console.log(hosCardArr) in then has content
let hosCardArr: any[] = [];
useEffect(() => {
getHosList({ _location: location, _level: level }).then(function (
response: returnHosInfo[],
) {
let arr: any[] = [];
for (let i = 0; i < response.length; i++) {
let e: returnHosInfo = response[i]
if (i % 2 == 0) {
arr.push(<HosCard name={e.name} level={e.level} openTime={e.openTime} domLocation='left' />)
} else {
arr.push(<HosCard name={e.name} level={e.level} openTime={e.openTime} domLocation='right' />)
}
}
hosCardArr = arr
});
});
In this code below, I render the array, using console.log(hosCardArr) in <div><div/> the result is []
<div>{hosCardArr}</div>
The end result is that the elements in the array are not displayed
The focus of this question is on data flow,If I don't use state, it will render the array empty and not updated
const [hosCardArr, setHosCardArr] = useState<any[]>([]);
useEffect(() => {
getHosList({ _location: location, _level: level }).then(function (
response: returnHosInfo[],
) {
let arr: any[] = [];
for (let i = 0; i < response.length; i++) {
let e: returnHosInfo = response[i]
if (i % 2 == 0) {
arr.push(<HosCard name={e.name} level={e.level} openTime={e.openTime} domLocation='left' />)
} else {
arr.push(<HosCard name={e.name} level={e.level} openTime={e.openTime} domLocation='right' />)
}
}
setHosCardArr(arr)
});
}, []);
you must use .map function to render each item of the array , like this :
return (
<>
{
hosCardArr.map((hos,index) =>
<div key={index}>{hos}</div>
);
}
</>
)

Firebase upload multiple files and get status

I have a React form where the user can upload multiple files. These are stored in fileList
async function uploadFiles(id) {
try {
const meta = await storageUploadFile(fileList, id);
console.log(meta);
} catch (e) {
console.log(e);
}
}
This calls my helper function that uploads the files to Firebase
export const storageUploadFile = function(files, id) {
const user = firebase.auth().currentUser.uid;
return Promise.all(
files.map((file) => {
return storage.child(`designs/${user}/${id}/${file.name}`).put(file)
})
)
};
What I'd like is on calling uploadFiles, get the total filesize of all items, and then show the overall progress.
At the moment, my code is only returning the file status in an array on completion
[
{bytesTransferred: 485561, totalBytes: 485561, state: "success"},
{bytesTransferred: 656289, totalBytes: 656289, state: "success"}
]
This is the way i do it:
import Deferred from 'es6-deferred';
export const storageUploadFile = function(files, id) {
const user = firebase.auth().currentUser.uid;
// To track the remaining files
let itemsCount = files.length;
// To store our files refs
const thumbRef = [];
// Our main tasks
const tumbUploadTask = [];
// This will store our primses
const thumbCompleter = [];
for (let i = 0; i < files.length; i += 1) {
thumbRef[i] = storage.ref(`designs/${user}/${id}/${file.name}`);
tumbUploadTask[i] = thumbRef[i].put(files[i]);
thumbCompleter[i] = new Deferred();
tumbUploadTask[i].on('state_changed',
(snap) => {
// Here you can check the progress
console.log(i, (snap.bytesTransferred / snap.totalBytes) * 100);
},
(error) => {
thumbCompleter[i].reject(error);
}, () => {
const url = tumbUploadTask[i].snapshot.metadata.downloadURLs[0];
itemsCount -= 1;
console.log(`Items left: ${itemsCount}`)
thumbCompleter[i].resolve(url);
});
}
return Promise.all(thumbCompleter).then((urls) => {
// Here we can see our files urls
console.log(urls);
});
};
Hope it helps.

How to create a pagination in Redux from an array received by API

I want to create a pagination for items received by the Hacker News API.
The received data contains 500 story IDs and display the items 10 per page
To my knowledge, the API does not have a server-side pagination
So far, I fetch the data in redux
axios
.get(`${API_URL}/topstories.json`)
.then(response => {
dispatch(getAllTopStoriesIsLoading(false));
dispatch(getAllTopStoriesSuccess(response.data));
const itemsPerPage = 10;
const itemCount = response.data.length;
const totalPages = Math.ceil(itemCount / itemsPerPage);
})
I tried to set a for loop inside the .then
let startIndex = 0;
for (let i = 1; i <= totalPages; i + 1) {
itemsOnPage = response.data.slice(startIndex, startIndex + itemsPerPage)
startIndex += itemsPerPage;
}
This results in an infinite loop.
I would like to have items stored in the redux store as
pages: {
1: [ {...}, {...}, {...}],
2: [...],
...
}
or similar
Try this solution:
axios
.get(`https://hacker-news.firebaseio.com/v0/topstories.json`)
.then(response => {
//dispatch(getAllTopStoriesIsLoading(false));
let page = 1;
const itemsPerPage = 10;
const responData = {};
response.data.map(item => {
if (!responData[page]) {
responData[page] = [];
} else if (responData[page].length >= itemsPerPage) {
current++;
responData[page] = [];
}
responData[current].push(item);
});
console.log('===responData===', responData);
//dispatch(getAllTopStoriesSuccess(responData));
});

Resources