React Native - Not able to add and delete data from array correctly - reactjs

I am creating an App in which I have two screens -- One is Feed and Bookmark. Each Feed has bookmark icon from which we can add and delete bookmark. If I add bookmark from feed then It will be added to list and if I delete that then list will be updated with existing once but the issue is that sometime data added double at the time of addition and sometimes at time of deletion array did not get the index of selected item and stays there and sometimes my list got disturbed with showing half items.
Code to click bookmark button on feed
const selectBookmark = () => {
item.bookmarked = !item.bookmarked;
setBookMarkSelected(!item.bookmarked);
setBookmarkClicked(true);
setBookmarkLoader(true);
};
Call API each time at updating bookmark
const bookmarkResponse = await addDeleteBookmark(
email,
userId,
item.cardId,
userSelectedChannel,
token,
item.bookmarked,
item.createdAt,
item.cardType,
)
.then(res => {
setBookmarkLoader(false);
if (res !== 'error') {
console.log('not in else');
updatebookMark();
} else {
console.log(' in else');
item.bookmarked = !item.bookmarked;
}
})
.catch(function (error) {
setBookmarkLoader(false);
});
};
**when I get response from API I call updateBookmark function too update local database **
const updatebookMark = () => {
// code to update feed Array locally
let newArray = [...feedArray];
let id = item.cardId;
const index = newArray.findIndex(object => {
return object.cardId === id;
});
if (index !== -1) {
newArray[index].bookmarked = item.bookmarked;
addFeedsToLocalDB(newArray);
}
// code to update bookmark Array locally
let bookmarks = [...bookmarkArray];
// bookmark added then add new bookmark
if (item.bookmarked) {
const index = bookmarkArray.findIndex(object => {
return object.cardId === id;
});
if (index === -1) {
bookmarks.push(item);
addBookMarksTOLocalDB(bookmarks);
}
} else {
// if deletion then delete from bookmark
const indexBookmark = bookmarks.findIndex(object => {
return object.cardId === id;
});
console.log('bookmark card indexBookmark image', indexBookmark);
bookmarks.splice(indexBookmark, 1);
// console.log('bookmarked after splicing image', bookmarks);
addBookMarksTOLocalDB(bookmarks);
// setBookmarksArray(bookmarks);
}
let homeArray = [...homeCards];
const indexHome = newArray.findIndex(object => {
return object.cardId === id;
});
if (indexHome !== -1) {
homeArray[indexHome].bookmarked = item.bookmarked;
addHomeToLocalDB(homeArray);
}
};
but the issue is that this addition and deletion bookmark is causing issue and I am not able to get that.

Related

I want to save array.map values in different column in DB using API's React JS

The senerio is that when choose categories using checkbox those checked box who are slected save their values in db in different column.
const checkListNames = check.map((item) => item.name)
values in want to save in different columns.
Getting output such as :
['A stage is required', 'Themed decoratiions are essential to my event'].
Want to save these values in different columns
const handleSubmit = (e) => {
e.preventDefault();
if (check.length > 0) {
const checkListNames = check.map((item) => item.name);
let formData = new FormData();
formData.append('list_category', categoryId);
formData.append('name', checkListNames);
formData.append('event_id', get_all_data.data7);
formData.append('created_by', '629829078779cc4a00139c9a');
for (var pair of formData.entries()) {
console.log(pair[0] + ' - ' + pair[1]);
}
api
.post('checklist', formData)
.then((response) => {
const { data } = response;
if (data.status == '1') {
toast.success('Checklist added successfully');
history.push('/CheckList');
} else {
toast.error('Something went wrong !');
}
})
.catch((error) => {
throw error;
});
} else {
toast.error('Select atleast one category');
return false;
}
};

Twilio + React: How to change audio or video input device during a call?

I've been looking at the documentation but I can't figure it out. When a user selects a different device, the other users can't hear that person anymore. This must mean that something is going right with the unpublishing of tracks, right? I'm not sure.
This is my code for a user to change devices:
const setDevice = (device) => {
if(!room) return
let deviceId = device.deviceId
const localParticipant = room.localParticipant
if(device.kind === 'audioinput'){
setSelectedAudioDevice(device.label)
Video.createLocalAudioTrack({
deviceId: {exact: deviceId}
}).then((localAudioTrack) => {
const tracks = localParticipant.audioTracks
tracks.forEach((track) => {
localParticipant.unpublishTrack(track.track)
})
localParticipant.publishTrack(localAudioTrack)
})
} else if(device.kind === 'videoinput'){
setSelectedVideoDevice(device.label)
Video.createLocalVideoTrack({
deviceId: {exact: deviceId}
}).then((localVideoTrack) => {
const tracks = localParticipant.videoTracks
tracks.forEach((track) => {
localParticipant.unpublishTrack(track.track)
})
localParticipant.publishTrack(localVideoTrack)
})
}
}
Each participant has its own component in which they subscribe to tracks. However, this code was from one of the Twilio examples, so I'm not entirely sure how it works.
const trackpubsToTracks = (trackMap) =>
Array.from(trackMap.values())
.map((publication) => publication.track)
.filter((track) => track !== null);
useEffect(() => {
setVideoTracks(trackpubsToTracks(participant.videoTracks));
setAudioTracks(trackpubsToTracks(participant.audioTracks));
const trackSubscribed = (track) => {
if (track.kind === "video") {
setVideoTracks((videoTracks) => [...videoTracks, track]);
} else if (track.kind === "audio") {
setAudioTracks((audioTracks) => [...audioTracks, track]);
}
};
const trackUnsubscribed = (track) => {
if (track.kind === "video") {
setVideoTracks((videoTracks) => videoTracks.filter((v) => v !== track));
} else if (track.kind === "audio") {
setAudioTracks((audioTracks) => audioTracks.filter((a) => a !== track));
}
};
participant.on("trackSubscribed", trackSubscribed);
participant.on("trackUnsubscribed", trackUnsubscribed);
return () => {
setVideoTracks([]);
setAudioTracks([]);
participant.removeAllListeners();
};
}, [participant]);
useEffect(() => {
const videoTrack = videoTracks[0];
if (videoTrack) {
videoTrack.attach(videoRef.current);
return () => {
videoTrack.detach();
};
}
}, [videoTracks]);
useEffect(() => {
const audioTrack = audioTracks[0];
if (audioTrack) {
audioTrack.attach(audioRef.current);
return () => {
audioTrack.detach();
};
}
}, [audioTracks]);
If anyone knows how I can handle device switching mid-call, I'd greatly appreciate it.
Twilio developer evangelist here.
I have found that the best order of operations here is:
Unpublish the local participant’s existing track from the room, this will trigger the trackRemoved event on the room for any other participants
Detach the existing track from the page
Stop the track completely
Request the new track with createLocal(Video|Audio)Track
Attach the new track to the page
Publish the new track to the room, triggering the trackAdded event on the room for the other participants
This is especially true for iOS devices which do not let you access more than one camera at a time.
Here is some code I've used before, though not in a React application:
function stopTracks(tracks) {
tracks.forEach(function(track) {
if (track) { track.stop(); }
})
}
function updateVideoDevice(event) {
const select = event.target;
const localParticipant = activeRoom.localParticipant;
if (select.value !== '') {
const tracks = Array.from(localParticipant.videoTracks.values()).map(
function(trackPublication) {
return trackPublication.track;
}
);
localParticipant.unpublishTracks(tracks);
detachTracks(tracks);
stopTracks(tracks);
Video.createLocalVideoTrack({
deviceId: { exact: select.value }
}).then(function(localVideoTrack) {
localParticipant.publishTrack(localVideoTrack);
log(localParticipant.identity + ' added track: ' + localVideoTrack.kind);
const previewContainer = document.getElementById('local-media');
attachTracks([localVideoTrack], previewContainer);
});
}
}
You can see the entire application in this repo on GitHub and I wrote about it here.
I think the React example you're referring to was one of mine too. I actually had a go at adding camera changes to that repo on a branch. It was apparently a year ago, but you can see the updates here. Hopefully that can point you in the right direction too.

(Refactor/Improve) Loop to make API calls and manupilate Array following the "no-loop-func"

Despite looking and following numerous answers here at stackoverflow,I have still failed to refactor this code to abide by the ESLint no-loop-func.
I keep getting the following warning, despite my efforts to refactor the code:
Compiled with warnings.
Function declared in a loop contains unsafe references to variable(s) 'lastResult', 'biologyBooks', 'page' no-loop-func
Here's the code:
import React from 'react';
import { apiFullCall } from '../../apiHelper';
const MyComponent = props => {
const [state, setState] = React.useState({ total: 0, biologyBooksByAuthor: [] });
let isLoaded = React.useRef(true);
const token = sessionStorage.getItem('token');
const authorID = sessionStorage.getItem('author_id');
const getBooks = async() => { // fetch items
let page = 1;
let scienceBooks, biologyBooks;
// create empty arrays to store book objects for each loop
let scienceBooks = biologyBooks = [];
// create a lastResult object to help check if there is a next page
let lastResult = { next: null };
do { // the looping - this is what I have failed to refactor
try {
await apiFullCall( // Make API calls over paginated records
'',
token,
'get',
`books/?author_id=1&page=${page}`
).then(res => {
if (res) {
const { status, body } = res;
if (status === 200 || status === 201) {
lastResult = body; // assign lastResult to pick "next"
body &&
body.results &&
body.results.map(eachBook => { // we map() over the returned "results" array
// the author with queried "author_id" writes science books;
// so we add each book (an object) into the science category
scienceBooks.push(eachBook);
// We then filter the author's biology books (from other science books)
biologyBooks = scienceBooks.filter(
({ is_biology }) =>
typeof(is_biology) === "boolean" && is_biology === true
);
return null;
}
);
// increment the page with 1 on each loop
page++;
}
}
}).catch(error => console.error('Error while fetching data:', error));
} catch (err) { console.error(`Oops, something went wrong ${err}`); }
// keep running until there's no next page
} while (lastResult.next !== null);
// update the state
setState(prevState => ({
...prevState, total: scienceBooks.length, biologyBooksByAuthor: biologyBooks,
}));
};
React.useEffect(() => { // fetch science books by author (logged in)
if (isLoaded && authorID) {
getBooks();
};
return function cleanup() {...}; // clean up API call, on unmount
}, [isLoaded, authorID]);
return (
// render the JSX code
);
}
Please note that I actually declared the said variables lastResult, biologyBooks and page outside the "do-while".
Any help or clues will be greatly appreciated.
The function the warning is referring to is the .then callback, if you're using async/await stick to it, try removing the .then part by assigning the result to a variable instead and remove the unnecessary .map, you can concatenate previous results with spread operator or .concat.
import React from 'react';
import { apiFullCall } from '../../apiHelper';
const MyComponent = props => {
const [state, setState] = React.useState({
total: 0,
scienceBooksByAuthor: [],
});
const isLoaded = React.useRef(true);
const token = sessionStorage.getItem('token');
const authorID = sessionStorage.getItem('author_id');
const getBooks = async () => {
// fetch items
let page = 1;
let scienceBooks = [];
// create a lastResult object to help check if there is a next page
let lastResult = { next: null };
do {
// the looping - this is what I have failed to refactor
try {
const res = await apiFullCall(
// Make API calls over paginated records
'',
token,
'get',
`books/?author_id=1&page=${page}`,
);
if (res) {
const { status, body } = res;
if (status === 200 || status === 201) {
lastResult = body; // assign lastResult to pick "next"
// concatenate new results
scienceBooks = [
...scienceBooks,
...((lastResult && lastResult.results) || []),
];
// increment the page with 1 on each loop
page += 1;
}
}
} catch (err) {
console.error(`Oops, something went wrong ${err}`);
}
// keep running until there's no next page
} while (lastResult.next !== null);
const biologyBooks = scienceBooks.filter(
({ is_biology }) =>
typeof is_biology === 'boolean' && is_biology === true,
);
// update the state
setState(prevState => ({
...prevState,
total: scienceBooks.length,
scienceBooksByAuthor: scienceBooks,
}));
};
React.useEffect(() => {
// fetch science books by author (logged in)
if (isLoaded && authorID) {
getBooks();
}
return function cleanup() {...}; // clean up API call, on unmount
}, [isLoaded, authorID]);
return (
// render the JSX code
);
};

When I click the delete button the top item on the list deletes. How can I fix it?

So I am trying to delete user name and image when in this panel I created. When I click the delete button on any item the first item on the list automatically deletes. WHat can I do to ensure the right item on the list gets deleted?
showfriendsrequest = () => {
const { show } = this.state;
let URL = 'https://swapi.co/api/people/';
let HEADERS = {'content-type':'application/json', 'authorization':'sdjfjdskfj45j4ekj'};
axios.get(URL, HEADERS)
.then((response) => {
let usersData = response.data.results;
console.log(usersData);
let users = [{name:"",img:""}];
let names = [];
let imgs = [];
for (let i=0; i<usersData.length; i++) {
let id = i;
let currentName = usersData[i]['name'];
let currentImages = usersData[i]["image"]
users.push({"id":id, 'name':currentName, "img":currentImages});
}
this.setState({users, show:!show});
});
}
deletefriendrequest = (index,e) => {
const users = Object.assign([], this.state.users);
users.splice(index, 1);
this.setState({users:users})
alert(`${this.state.users.name}`)
}
addfriend = () => {
alert(`You just added a new friend ${this.state.name}`);
}
You shouldn't use mutation, instead you can filter the array and replace your delete function with something like
deletefriendrequest = (index, e) => {
this.setState({
users: this.state.users.filter((user, i)=> i !== index )
}
Or better even, you could target the user by id instead of index, and on the onClick simply pass the user.id

How to select multiple checkbox in reactjs?

The problem is that I need to pass array of object , I can not get my accepted data .My accepted data will be this format. However, user can remove by using unchecked.
{
notification : {group:["can_view","can_create", "can_delete","can_update","can_upload","can_download"],
topGroup:["can_view","can_create", "can_delete","can_update","can_upload","can_download"}
}
handleAllChecked = (id, role, data) => event => {
let fruites = this.state.fruites;
fruites
.filter(f => f.groupId === id)
.forEach(fruite => {
if (event.target.checked === true) {
fruite.isChecked = event.target.checked;
console.log(data);
} else {
fruite.isChecked = false;
}
});
this.setState({ fruites: fruites });
};
here is my codesanbox , You can easily understand
https://codesandbox.io/s/fragrant-http-v35lf

Resources