I'm trying to update a state using useState hook, however the state won't update. I've checked how to fix it but really have no idea about it what cause this point. This is the whole code I didnt include the urls and import files...
When onchange method trigger ilceZoom function event has value so ı can get it evt.value example values is "1234" but I can not set it using useState future
const ilceUrl = 'URL';
const AddressSearchMaks = (props) => {
useEffect(() => {
ilceLoad();
}, []);
const [ ilceler, setIlceler ] = useState([]);
const [ selectedIlce, setSelectedIlce ] = useState(null);
let queryTask;
let query;
let sfs;
let lineSymbol;
let polygon;
let polyline;
let graphic;
let extent;
let point;
let wMercatorUtils;
let rfConverter;
loadModules([
'esri/tasks/query',
'esri/tasks/QueryTask',
'esri/symbols/SimpleFillSymbol',
'esri/symbols/SimpleLineSymbol',
'esri/geometry/Polygon',
'esri/geometry/Polyline',
'esri/geometry/webMercatorUtils',
'esri/geometry/Extent',
'esri/geometry/Point',
'esri/graphic',
'esri/Color',
'libs/ReferenceConverter'
]).then(
(
[
Query,
QueryTask,
SimpleFillSymbol,
SimpleLineSymbol,
Polygon,
Polyline,
webMercatorUtils,
Extent,
Point,
Graphic,
Color,
referenceConverter
]
) => {
queryTask = QueryTask;
query = Query;
polygon = Polygon;
polyline = Polyline;
graphic = Graphic;
extent = Extent;
point = Point;
wMercatorUtils = webMercatorUtils;
rfConverter = referenceConverter;
sfs = new SimpleFillSymbol(
SimpleFillSymbol.STYLE_SOLID,
new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([ 0, 255, 255 ]), 4),
new Color([ 140, 140, 140, 0.25 ])
);
lineSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([ 0, 255, 255 ]), 4).setWidth(4);
}
);
const getAdres = async (url) => {
let response = await fetch(url);
let data = await response.json();
let list = [];
data.AdresList.Adresler.Adres.forEach((item) => {
list.push({
label: item.ADI,
value: item.ID,
lat: item.LAT,
lon: item.LON
});
});
return list;
};
async function ilceLoad() {
let ilceList = await getAdres(ilceUrl);
setIlceler(ilceList);
}
const convertExtent = (lat, lon) => {
let p;
let ext;
const sr = props.map.spatialReference;
if (sr.wkid == 102100) {
const _p = wMercatorUtils.lngLatToXY(lon, lat);
ext = extent({
xmin: _p[0],
ymin: _p[1],
xmax: _p[0],
ymax: _p[1],
spatialReference: props.map.spatialReference
});
} else {
const res = rfConverter.WgsToItrf(lat, lon);
ext = extent({
xmin: res.x,
ymin: res.y,
xmax: res.x,
ymax: res.y,
spatialReference: props.map.spatialReference
});
p = point(res.x, res.y);
}
p.spatialReference = sr;
return ext;
};
const ilceZoom = (evt) => {
setSelectedIlce(evt.value);
console.log('selectedIlce', selectedIlce);
setError(false);
console.log('error', error);
const qTask = queryTask(maksIlce);
const q = query();
q.returnGeometry = true;
q.outFields = [ '*' ];
q.outSpatialReference = { wkid: 5254 };
q.where = `KIMLIKNO=${evt.value}`;
qTask.execute(q, (evt) => {
const polyGon = polygon({
rings: evt.features[0].geometry.rings
});
props.map.graphics.add(graphic(polyGon, sfs));
});
const extent = convertExtent(evt.lat, evt.lon);
props.map.setExtent(extent);
mahalleLoad();
};
return (
<Select name='adresSelect' options={ilceler} onChange={(e) => ilceZoom(e)} placeholder='İlçe Seçiniz' />
);
};
const mapStateToProps = (state) => ({
map: state.map.map
});
export default connect(mapStateToProps, null)(AddressSearchMaks);
It can be related for some environment binding issue. Try to use the the setState as function:
useEffect(() => {
ilceLoad();
}, []);
const [ ilceler, setIlceler ] = useState([]);
const [ selectedIlce, setSelectedIlce ] = useState(null);
async function ilceLoad() {
let ilceList = await getAdres(ilceUrl);
setIlceler(ilceList); // update the state, it works here
}
const ilceZoom = (evt) => {
setSelectedIlce(prev => {
console.log("prev: ", prev);
console.log("evt.value: ", evt.value);
return evt.value;
});
const qTask = queryTask(url);
const q = query();
q.returnGeometry = true;
q.outFields = [ '*' ];
q.outSpatialReference = { wkid: 5254 };
q.where = `VARIABLE NAME=${evt.value}`;
qTask.execute(q, (evt) => {
const polyGon = polygon({
rings: evt.features[0].geometry.rings
});
props.map.graphics.add(graphic(polyGon, sfs));
});
const extent = convertExtent(evt.lat, evt.lon);
props.map.setExtent(extent);
};
Can you try like this. Because, in your code, you setting the data in selectedIlce, but before it re-render, your trying to checking the value in the console, so better use your console outside the event function, so that when it get updated, it will reflect in the console.
console.log('selectedIlce', selectedIlce);
const ilceZoom = (evt) => {
setSelectedIlce(evt.value);
....
}
Related
I want to return the results to Text elements, but I'm not able to use map on the state that it is stored in.
Here is my code:
const [specData, setSpecData] = useState([]);
const ActionType = ['Existing Construction', 'New Construction'];
const [ actionType, setActionType ] = useState("");
const [ capacity, setCapacity ] = useState("");
const [ seer2, setSeer2 ] = useState("");
const [ eer2, setEer2 ] = useState("");
const [ existingTon, setExistingTon ] = useState("");
var data = `{"specifications": {
"ARI_Reference_No": " ",
"ClimateZone": 2,
"Action_Type_Operation": "${actionType}",
"Condensor_Brand_Name": " ",
"Condensor_Model_No": " ",
"Condensor_Serial_No": " ",
"Capacity_BTUH2": "${capacity}",
"SEER2": "${seer2}",
"EER2": "${eer2}",
"Replaced_Unit_Type": "Central Air Conditioner",
"Existing_BrandName": null,
"Old_Unit_Tonnage": ${existingTon},
"Existing_Model": null,
"Existing_Serial": null,
"ReplacedUnitType": null,
"ManualJ": true,
"Multi_System_Change_Out": false,
"Program_Option": "HEE HVAC Program Option"
}}`
const APICall = async () => {
var xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
console.log(this.responseText);
const result = this.responseText;
setSpecData(result)
}
});
xhr.open('POST', 'https://api-plus.anbetrack.com/etrm-gateway/etrm/api/v1/etrm/Texas PUC/R-HV-AC/PUCT TRM V10/version/10/execute?token=');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('cache-control', 'no-cache');
xhr.send(data);
}
This is how it returns the request from the API:
{
"result": {
"Nominal_New_Unit_Tonnage": 3.5,
"kWh": 3302.9725609756088,
"kW": 1.2162244897959178,
"I": 1344.898672688993
},
"calculationTime": 0
}
I have tried to use map function and set the state as a string and a array, but it still throws the error
undefined is not a function(near'...specData.map...')
This is how I was trying to render it:
<Text>Result {specData.map((res) => {
return(
<Text>{res.result.Nominal_New_Unit_Tonnage}</Text>
)
})}</Text>
I need to get localMediaStream in one effect, while it is set in another effect. Please tell me why in this context it is always null (if you do not set it in the same effect), but in this case I have a duplicate userMedia. Consequences - the camera does not go out when I call track.stop(). Based on this package
const peerConnections = useRef({});
const localMediaStream = useRef(null);
const peerMediaElements = useRef({
[LOCAL_VIDEO]: null,
});
useEffect(() => {
async function handleNewPeer({peerID, createOffer}) {
if (peerID in peerConnections.current) {
return console.warn(`Already connected to peer ${peerID}`);
}
peerConnections.current[peerID] = new RTCPeerConnection({
iceServers: freeice(),
});
peerConnections.current[peerID].onicecandidate = event => {
if (event.candidate) {
socket.emit(ACTIONS.RELAY_ICE, {
peerID,
iceCandidate: event.candidate,
});
}
}
let tracksNumber = 0;
peerConnections.current[peerID].ontrack = ({streams: [remoteStream]}) => {
tracksNumber++
if (tracksNumber === 2) { // video & audio tracks received
tracksNumber = 0;
addNewClient(peerID, () => {
if (peerMediaElements.current[peerID]) {
peerMediaElements.current[peerID].srcObject = remoteStream;
} else {
// FIX LONG RENDER IN CASE OF MANY CLIENTS
let settled = false;
const interval = setInterval(() => {
if (peerMediaElements.current[peerID]) {
peerMediaElements.current[peerID].srcObject = remoteStream;
settled = true;
}
if (settled) {
clearInterval(interval);
}
}, 1000);
}
});
}
}
/*localMediaStream.current = await navigator.mediaDevices.getUserMedia({
audio: audio,
video: video
})*/
localMediaStream.current.getTracks().forEach(track => { // localMediaStream null
peerConnections.current[peerID].addTrack(track, localMediaStream.current);
});
if (createOffer) {
const offer = await peerConnections.current[peerID].createOffer();
await peerConnections.current[peerID].setLocalDescription(offer);
socket.emit(ACTIONS.RELAY_SDP, {
peerID,
sessionDescription: offer,
});
}
}
socket.on(ACTIONS.ADD_PEER, handleNewPeer);
return () => {
socket.off(ACTIONS.ADD_PEER);
}
}, []);
// The installation, everything is as in the source, it did not work until I added the crutch above, but when it came to stopping the video stream, a bug appeared with the camera always on
useEffect(() => {
async function startCapture() {
console.log('start capture');
localMediaStream.current = await navigator.mediaDevices.getUserMedia({
audio: audio,
video: video
}).catch(console.log);
addNewClient(LOCAL_VIDEO, () => {
const localVideoElement = peerMediaElements.current[LOCAL_VIDEO];
if (localVideoElement) {
localVideoElement.volume = 0;
localVideoElement.srcObject = localMediaStream.current;
}
});
}
startCapture().then((data) => socket.emit(ACTIONS.JOIN, {room: roomID})).catch((e) => console.error(e)).finally(() => console.log('finally'));
console.log(roomID);
return () => {
localMediaStream.current.getTracks().forEach(track => track.stop());
socket.emit(ACTIONS.LEAVE);
};
}, [roomID]);
Thanks you very much.
I'm trying to generate an array with values as follows:
{ name: 'John', age: 35, employer: 'ABC', paycheck: 5,000, last_paycheck: 4,900, change: 100 } // new array
with the initial values in the array as follow:
{ name: 'John', age: 35, employer: 'ABC' } //inital array
the function convertData() is handling all the array conversion.
async function convertData(data){
if(data.length === 0) return data;
// generates new array
const convertedDataArray = await data.map( async (row) =>{
let name = row.name
let paycheck = 0;
let last_paycheck = 0;
let change = 0;
const response = await axios.get('/getData', {params: {
name,
}});
let apiData = response.data.data;
if(apiData.length > 0){
let newData = apiData[0];
let oldData = apiData[1];
change = newData.payCheck - oldData.payCheck;
paycheck = newData.payCheck;
last_paycheck = oldData.payCheck;
}
console.log(apiData); // prints records up to 100 elements
return {...row, paycheck, last_paycheck, change };
});
console.log(convertedDataArray);// prints [Promise]
return Promise.all(convertedDataArray).then(() =>{
console.log(convertedDataArray); // prints [Promise]
return convertedDataArray;
});
};
where convertData() is called:
const response = await axios.get('/getEmployees',{params: {
token: id,
}});
const dataRows = response.data; //inital array
const tableRows = await convertData(dataRows);
return Promise.all(tableRows).then(() =>{
console.log(tableRows); // prints [Promise]
dispatch(setTableRows(tableRows));
});
I'm not sure why i keep getting Promise return I am still learning how to use promise correctly. Any help would be great, thank you in advance!
You should get a array of promises and use Promises.all to get all the data first.
Then use map() function to construct your data structure.
Example below:
async function convertData(data) {
try {
if (data.length === 0) return data;
const arrayOfPromises = data.map(row =>
axios.get("/getData", {
params: {
name: row.name,
},
})
);
const arrayOfData = await Promise.all(arrayOfPromises);
const convertedDataArray = arrayOfData.map((response, i) => {
const apiData = response.data.data;
let paycheck = 0;
let last_paycheck = 0;
let change = 0;
if (apiData.length > 0) {
const newData = apiData[0];
const oldData = apiData[1];
change = newData.payCheck - oldData.payCheck;
paycheck = newData.payCheck;
last_paycheck = oldData.payCheck;
}
return { ...data[i], paycheck, last_paycheck, change };
});
return convertedDataArray;
} catch (err) {
throw new Error(err);
}
}
(async function run() {
try {
const response = await axios.get("/getEmployees", {
params: {
token: id,
},
});
const dataRows = response.data;
const tableRows = await convertData(dataRows);
dispatch(setTableRows(tableRows));
} catch (err) {
console.log(err);
}
})();
I want to add an All Option to my existing select box.
Select box is creating with some API data. With the API data set I want to add an ALL option above.
This is my code.
const useChemicals = () => {
const [data, setData]: any = useState([]);
useEffect(() => {
const getChemicalsData = async () => {
try {
const results = await searchApi.requestChemicalsList();
if (results.data) {
let groupCount = 0;
const chemList: any = [];
results.data.data.chemicals.map((chemical: any, index: number) => {
if (chemical.key === '') {
chemList.push({
label: chemical.value,
options: [],
});
}
});
results.data.data.chemicals.map((chemical: any, index: number) => {
if (chemical.key === '') {
if (index > 1) {
groupCount += 1;
}
} else {
chemList[groupCount].options.push({
label: chemical.value,
value: chemical.key,
});
}
});
setData([...chemList]);
}
} catch (e) {}
};
getChemicalsData();
}, []);
return data && data;
};
export default useChemicals;
How can I add this. Please help me, I am new to React.
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.