Am trying to create a real time voting using Pusher, typescript and react native, but the candidates array is not being updated and displayed on the useEffect function. but when I run the same code lines from a normal vote it works (the candidates array is updated and displayed correctly);
const [candidates, setCandidates] = useState([]);
const vote = (id, position, name, name2) => {
var newVoteData = ({ voterName: votingData.voterName, voterId: votingData.voterId, position: position, candidateId: id, candidateName: name });
setProcessingModal(true);
fetch("http://172.20.10.4:8000/mobile/vote", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(newVoteData),
})
.then((response) => response.json())
.then((data) => {
if (data.status == "ok") {
// This block of code works, updates the particular
// candidate voteCount and setCandidates correctly
setProcessingModal(false);
alert("Yay!!! , you have successfully voted");
const updatedData = candidates.map(x => (x.id === id ? { ...x, voteCount: data.voteCount } : x)); //updates votecount on candidate
let newArr = updatedData.sort((x, y) => {
return y.voteCount - x.voteCount;
});
setCandidates(updatedData);
} else {
setProcessingModal(false);
alert(data);
}
})
.catch((error) => {
setProcessingModal(false);
alert(error);
console.error("Error:", error);
});
};
the below useEffect function is where am having issues, the array for some reason is not being updated
useEffect(() => {
const liveUpdateCandidates = (id, voteCount) => {
alert(voteCount);
const updatedData = candidates.map(x => (x.id === id ? { ...x, voteCount: voteCount } : x));//updates votecount on candidate does not work here
console.log("afer");
let newArr = updatedData.sort((x, y) => {
return y.voteCount - x.voteCount;
});
setCandidates(newArr);
};
//Pusher.logToConsole = true;
const pusher = new Pusher("3580cab8bee36d295917", {
cluster: "eu",
encrypted: true,
});
const channel = pusher.subscribe("votebooth-channel");
channel.bind("App\\Events\\BoothEvent", function(data) {
liveUpdateCandidates(data.candidateId, data.voteCount);
});
return (() => {
pusher.unsubscribe("votebooth-channel");
// pusher.unsubscribe('channel_name2');
});
}, [candidates]);
Below is a sample of the returned array
[
{ "id": "3", "name": "Kwaku", "candidateUserId": null, "gender": "Male", "philosophy": "Good", "voteCount": "132" },
{ "id": "22", "name": "rose", "candidateUserId": null, "gender": "Female", "philosophy": "Php", "voteCount": "1" },
];
CodePudding user response:
There are a few things here I would fix.
First of all you are using a useEffect which has candidates
as a dependency and using setCandidates
inside of that useEffect. Dependencies in a useEffect mean it will trigger everytime the dependency value changes.
This means that the useEffect will enter into a loop and it will most likely crash and nothing will work.
Secondary, you are defining a value for newArr
which is never being used, you should remove that.
Finally, your code needs some refactoring. Try using one useEffect for the listener and another for the updating of data. Also, if it has several lines I would extract it to a function with a clear name of what it's doing.
CodePudding user response:
It appears the id variable is sent to liveUpdateCandidates function for some reason is been sent as string so I had to convert it to int first. like below
const liveUpdateCandidates = (id, voteCount) => {
alert(id);
var candId = parseInt(id);// the solution is to convert the id to int first
const updatedData = candidates.map(x => (x.id === candId ? { ...x, voteCount: voteCount } : x));//updates votecount on candidate
let newArr = updatedData.sort((x,y) => {return y.voteCount - x.voteCount});
setCandidates(newArr);
};