prevState showing updated state in componentDidUpdate - reactjs
I am using componentDidUpdate for calling a certain function when my props change.
the problem is that I am unable to compare it to prevState, because prevState also shows the updated state. So, I am not sure now how to compare new and old state.
why is this happening?
Here's the code
componentDidUpdate(prevProps,prevState){
console.log('prevProps',prevProps);
console.log('prevstate : ',prevState.urls.length);
console.log('prevProps : ',prevProps.urls.length);
console.log('new props in canvas :',this.props.urls.length);
}
now, i have removed the rest of the code, but in the console logs I can see that the value of urls length is coming as same in both prevState and the props.
the problem is that prevProps are showing the same value as current props and the prevState is showing the same value as current State.
so, I am kinda bewildered about how to compare!
can you tell why?
is this a bug??
I tried it with componentWillReceiveProps too earlier, but there also the same problem was coming up.
just to show how /where/when I am setting state
import React, { Component } from 'react';
import { Modal,Button,Icon,Select,Input,Row,Col,Spin} from 'antd';
//import { connect } from 'dva';
import SortableComp from './SortableComp';
import ViewPdfModal from './ViewPdfModal';
import SaveEditedFiles from './SaveEditedFiles';
import TripsForm from '../../routes/Trips/TripsForm';
import {getRequest,postRequest,successNotification,errorNotification} from '../../utils/server-request';
import styles from '../../routes/Trips/EditPdfDetailsModal.less';
export default class CanvasRender extends Component{
constructor(props){
super(props);
this.state={
urls:this.props.urls,
urlsOrder:[],
imgsrc:[],
viewFileModal:false
}
this.canvasRefs = {}
this.imageRefs = {}
}
componentDidMount(){
console.log('canvas mounted');
setTimeout(this.pdfConversion(this.props.urls),7000);
let urls = this.props.urls;
let urlsOrder = [];
urls.map((item)=>{
let newItem = item.replace('http://172.104.60.70/st_old/uploads/tripdoc/split/','');
if(this.props.type === 'maildoc'||this.props.type==='itinerary'||this.props.item && this.props.item.doctype === 'important' && this.props.item.doctypes && this.props.item.doctypes === 'emaildoc'){
newItem = item.replace(' http://172.104.60.70/st_old/uploads/maildoc/split','');
}else if(this.props.type === 'agency'){
newItem = item.replace('http://172.104.60.70/st_old/uploads/defaultdocs/7/split','');
}else if(this.props.type === 'clients'){
newItem = item.replace('http://172.104.60.70/st_old/uploads/clientsdoc/split','');
}
urlsOrder.push(newItem);
});
this.setState({
urlsOrder
});
/*
if(this.props.getNewOrderEditPdf){
this.props.getNewOrderEditPdf(urlsOrder);
}
this.props.dispatch({
type: 'global/savePdfOrder',
payload: urlsOrder
});
*/
}
componentDidUpdate(prevProps,prevState){
console.log('prevProps',prevProps);
console.log('prevstate : ',prevState.urls.length);
console.log('new props in canvas :',this.props.urls.length);
if(prevState.urls.length!= this.state.urlsOrder.length){
console.log('new props in canvas in IF :',this.props.urls);
let urls = this.props.urls;
let urlsOrder = [];
urls.map((item)=>{
let newItem = item.replace('http://172.104.60.70/st_old/uploads/tripdoc/split/','');
if(this.props.type === 'maildoc'||this.props.type==='itinerary'||this.props.item && this.props.item.doctype === 'important' && this.props.item.doctypes && this.props.item.doctypes === 'emaildoc'){
newItem = item.replace(' http://172.104.60.70/st_old/uploads/maildoc/split','');
}else if(this.props.type === 'agency'){
newItem = item.replace('http://172.104.60.70/st_old/uploads/defaultdocs/7/split','');
}else if(this.props.type === 'clients'){
newItem = item.replace('http://172.104.60.70/st_old/uploads/clientsdoc/split','');
}
urlsOrder.push(newItem);
});
this.setState({
urlsOrder
});
this.pdfConversion(this.props.urls);
}//end of if
}//end of didupdate
// static getDerivedStateFromProps(nextProps, prevState){
// console.log('props urls length :', nextProps.urls.length);
// console.log('state urls length :', prevState.urls.length);
// if(nextProps.urls.length!= prevState.urls.length){
// console.log('new props in canvas in IF :',nextProps.urls);
// let urls = nextProps.urls;
// let urlsOrder = [];
// urls.map((item)=>{
// let newItem = item.replace('http://172.104.60.70/st_old/uploads/tripdoc/split/','');
// if(nextProps.type === 'maildoc'||nextProps.type==='itinerary'||nextProps.item && nextProps.item.doctype === 'important' && nextProps.doctypes && nextProps.item.doctypes === 'emaildoc'){
// newItem = item.replace(' http://172.104.60.70/st_old/uploads/maildoc/split','');
// }else if(nextProps.type === 'agency'){
// newItem = item.replace('http://172.104.60.70/st_old/uploads/defaultdocs/7/split','');
// }else if(nextProps.type === 'clients'){
// newItem = item.replace('http://172.104.60.70/st_old/uploads/clientsdoc/split','');
// }
// urlsOrder.push(newItem);
// });
// return {
// urlsOrder,
// urls:nextProps.urls
// };
// }
// else return null;
// }
// componentWillReceiveProps(nextProps){
// console.log('props urls length :', nextProps.urls.length);
// console.log('state urls length :', this.state.urls.length);
// if(nextProps.urls.length!= this.state.urls.length){
// console.log('new props in canvas in IF :',nextProps.urls);
// let urls = this.props.urls;
// let urlsOrder = [];
// urls.map((item)=>{
// let newItem = item.replace('http://172.104.60.70/st_old/uploads/tripdoc/split/','');
// if(nextProps.type === 'maildoc'||nextProps.type==='itinerary'||nextProps.item && nextProps.item.doctype === 'important' && nextProps.doctypes && nextProps.item.doctypes === 'emaildoc'){
// newItem = item.replace(' http://172.104.60.70/st_old/uploads/maildoc/split','');
// }else if(nextProps.type === 'agency'){
// newItem = item.replace('http://172.104.60.70/st_old/uploads/defaultdocs/7/split','');
// }else if(nextProps.type === 'clients'){
// newItem = item.replace('http://172.104.60.70/st_old/uploads/clientsdoc/split','');
// }
// urlsOrder.push(newItem);
// });
// this.setState({
// urlsOrder,
// urls:nextProps.urls
// });
// this.pdfConversion(nextProps.urls);
// setTimeout(nextProps.hideLoading(),2000);
// }
// /*
// this.setState({
// urls:newUrls
// },()=>{
// this.pdfConversion(newUrls);
// });
// */
// }
pdfLoop = (item,index) => {
var that = this;
PDFJS.getDocument(item).then(function getPdfHelloWorld(pdf) {
//
// Fetch the first page
console.log('url is : ',item);
pdf.getPage(1).then(function getPageHelloWorld(page) {
var scale = 0.5;
var viewport = page.getViewport(scale);
let cref = 'canvas'+index;
let imgref ='img'+index;
console.log('cref no : ',cref);
console.log('img no : ',imgref);
// Prepare canvas using PDF page dimensions
//
var canvas = that.canvasRefs[cref];
//let imagez = that.imageRefs[imgref];
var context = canvas.getContext('2d');
context.globalcompositeoperation = 'source-over';
// context.fillStyle = "#fff";
//draw on entire canvas
//context.fillRect( 0, 0, canvas.width, canvas.height );
canvas.height = viewport.height;
canvas.width = viewport.width;
//imagez.src = canvas.toDataURL("image/png");
//
// Render PDF page into canvas context
//
//page.render({canvasContext: context, viewport: viewport});
var task = page.render({canvasContext: context, viewport: viewport})
task.promise.then(function(){
//console.log(canvas.toDataURL('image/png'));
let imgItem = {imgref:canvas.toDataURL('image/png'),page:index+1,rotate:0}
let newState = that.state.imgsrc;
newState[index] = imgItem;
//let newState = that.state.imgsrc.concat(imgItem);
that.setState({
imgsrc:newState
});
//imagez.src = canvas.toDataURL('image/png')
});
});
});
}
pdfConversion = (urls)=>{
/* this.props.dispatch({
type: 'global/savePdfOrder',
payload: urls
});*/
console.log('urls in pdf conversion : ',urls);
if(window.PDFJS){
console.log(this.state);
//let urls = this.props.urls;
for(var i = 0;i<urls.length;i++){
let newurl = urls[i];
//let newurl = 'http://172.104.60.70/st_old/uploads/defaultdocs/7/split/1527165241-42557/1_1527165241-42557.pdf';
console.log('url : ',newurl);
this.pdfLoop(newurl,i);
}
}
}
zoomPdf = (path)=>{
console.log('path is : ',path);
let url = path;
this.setState({
viewFileModal:true,
pdfToZoom:url
});
}
closeFileModal = ()=>{
this.setState({
viewFileModal:false
});
}
deletePdf = (data,path,index,e)=>{
console.log('item to delete : ',data);
console.log('index is : ',index);
console.log('pdfpath : ',path);
let newImgSrc = this.state.imgsrc.slice();
let newOrder = this.state.urlsOrder.slice();
newOrder.splice(index,1);
newImgSrc.splice(index,1);
this.setState({
imgsrc:newImgSrc,
urlsOrder:newOrder
});
if(this.props.getUrlUpdate){
this.props.getUrlUpdate(newOrder);
}else if(this.props.getNewPdfOrder){
this.props.getNewPdfOrder(newOrder);
}
/*
if(this.props.getNewOrderEditPdf){
this.props.getNewOrderEditPdf(newOrder);
}
this.props.dispatch({
type: 'global/savePdfOrder',
payload: newOrder
});*/
//also have to remove it from list which is sent to server on submit
// or another option is to create a list of parts that i send back to server, just before sending
/* let newUrls = [];
this.state.urls.map((d)=>{
if(d !== data){
newUrls.push(d);
}
});
this.setState({urls:newUrls},this.pdfConversion());
*/
}
rotatePdf = (item,index,path,e)=>{
let newImgSrc = this.state.imgsrc;
let rotate = '';
if(newImgSrc[index].rotate<4){
if((newImgSrc[index].rotate) ===3){
newImgSrc[index].rotate = 0;
rotate = 0;
}else{
newImgSrc[index].rotate = (newImgSrc[index].rotate)+1;
rotate = 90*(newImgSrc[index].rotate)
}
this.setState({
imgsrc:newImgSrc
})
}
let urlsOrder = this.state.urlsOrder;
let newItem = urlsOrder[index].replace('http://172.104.60.70/st_old/uploads/','');
let file = urlsOrder[index].replace('http://172.104.60.70/st_old/uploads/','').split('/')[3];
let num = file.split('_')[0];
let toReplace = '/'+file;
let filepath = '/'+ newItem.replace(toReplace,'');
console.log('pdfpath : ',path);
e.stopPropagation();
console.log('item data : ',item);
let url = devUrl + 'trip/retate_pdf/';
console.log('url is : ',url);
var formData = new FormData();
formData.append('filename',this.props.item.name);
formData.append('filepath',filepath);
formData.append('angle',rotate);
// filepath: /tripdoc/split/1528194456-85458
//angle: 90
//filename: 2_1527752445-64749.pdf
postRequest(url,formData, null,response=>{
console.log('response in data : ',response);
},error=>console.log(error));
// var that = this;
// fetch(url,{
// method: "post" ,
// credentials:'include',
// body:formData
// }).then((response)=>{
// return response.json();
// }).then((data)=>{
// return data;
// }).catch((err)=>console.log(err));
}
reorderArray = (oldIndex,newIndex,array)=>{
let elementMoved = array[oldIndex];
array[oldIndex]=array[newIndex];
array[newIndex]=elementMoved;
return array;
}
reOrder = (oldIndex,newIndex)=>{
let newImgSrc = this.state.imgsrc;
let newOrder = this.state.urlsOrder;
console.log('array before sorting : ',newOrder)
newImgSrc= this.reorderArray(oldIndex,newIndex,newImgSrc);
newOrder = this.reorderArray(oldIndex,newIndex,newOrder)
console.log('array after sorting : ',newOrder);
if(this.props.getNewPdfOrder){
this.props.getNewPdfOrder(newOrder);
}
/*
if(this.props.getNewOrderEditPdf){
this.props.getNewOrderEditPdf(newOrder);
}
this.props.dispatch({
type: 'global/savePdfOrder',
payload: newOrder
});*/
this.setState({
imgsrc:newImgSrc,
urlsOrder:newOrder
});
}
updateCategory = (value) =>{
this.setState({
categorySelected:value
});
}
render(){
let num = this.props.num;
let canvasDiv = [];
let imgsDiv = [];
if(this.state.imgsrc.length>0){
this.state.imgsrc.map((item,index)=>{
//let imgz = <img key={index} src={item.imgref} alt="pdfimg"/>;
let pdfpath = this.state.urlsOrder[index];
//let pdfIndex = pdfpath.replace('http://172.104.60.70/st_old/uploads/clientsdoc/split/','').split('/')[1].split('_')[0];
let pdfIndex = item.page;
let rotate = '';
let rotateStyle = null;
if(item.rotate){
rotate = 90*(item.rotate);
rotateStyle = {transform:`rotate(${rotate}deg)`};
}
//"http://172.104.60.70/st_old/uploads/clientsdoc/split/1529916893-26743/1_1529916878-36442.pdf"
let imgz = (<div> <div className={styles.pdfButtons} >
<span>Page No. {pdfIndex}</span>
<span className={styles.actIcons}>
<Icon onClick={(e)=>this.rotatePdf(item,index,pdfpath,e)} type="reload" /> <Icon onClick={(e)=>this.deletePdf(item,pdfpath,index,e)} type="close-circle-o" />
</span>
</div>
<img className={styles.imgThumb} style={rotateStyle} src={item.imgref} key={index+100} alt = "pdfimage"/><br/>
<span className={styles.zoom} ><Icon onClick={()=>this.zoomPdf(pdfpath)} type="search" /> </span>
</div>)
imgsDiv.push(imgz);
});
}
this.props.urls.map((item,index)=>{
let canv = <canvas key={index} style={{display:'none'}} ref={(ref) => this.canvasRefs[`canvas${index}`] = ref} > </canvas>;
canvasDiv.push(canv);
});
return(
<div>
{canvasDiv.length>0?canvasDiv:''}
{imgsDiv.length>0 && !this.props.showEditForm &&!this.props.showEmailUploadForm ? <SortableComp reOrder={this.reOrder} hideLoading={this.props.hideLoading} imgsDiv={imgsDiv} /> :''}
{this.props.type && this.props.type==='addDoc'? '' : <div>{this.props.type==='maildoc' &&this.props.whichTab==='itinerary'?
this.props.showEditForm ||this.props.type === 'maildoc' && this.props.showEmailUploadForm ? <TripsForm
getUpdatedData={this.props.getUpdatedData}
airlinesCategories={this.props.airlinesCategories}
updateAirlineCat={this.updateAirlineCat}
selectedAirlineCat = {this.state.selectedAirlineCat}
updateSelectedCategory={this.updateCategory}
categorySelected={this.state.categorySelected}
whichTab={this.props.whichTab}
// getUpdatedData={this.props.getUpdatedData}
closeModal={this.props.closeModal}
pdfOrder={this.state.urlsOrder}
// onSave={this.onSave}
categories={this.props.categories}
type={this.props.type}
tripid={this.props.tripid}
// item={this.props.item}
/>:''
:this.props.showEditForm && !this.props.uploadEmailDoc || this.props.showEmailUploadForm && this.props.uploadEmailDoc?<SaveEditedFiles
getUpdatedData = {this.props.getUpdatedData}
tripid={this.props.tripid}
whichTab={this.props.whichTab}
// impCategories={this.props.impCategories}
guidesCategories={this.props.guidesCategories}
librarycategories={this.props.librarycategories}
getClientDocs = {this.props.getClientDocs?this.props.getClientDocs:''} //from getclientdocs -
showSuccessMessage={this.props.showSuccessMessage} //from view client docs
closeModal={this.props.closeModal} // editpdf function from view client docs
hideSplitFiles={this.props.hideSplitFiles} //from editpdfmodal
clientid={this.props.clientid}
type={this.props.type} // from addclientdocmodal which is getting it from the card we click on
item={this.props.item} // it is itemToedit - getting from viewclientdocs
urlsOrder={this.state.urlsOrder} //was getting from editpdfmodal but now will get from canvasrender
categories={this.props.categories}
clientCategories={this.props.clientCategories}
impCategories={this.props.impCategories} // was getting from editpdfmodal and will still get it from there but pass through a number of components
/>:''}<br/></div>}
{this.state.viewFileModal?<ViewPdfModal viewFileModal={this.state.viewFileModal} closeModal={this.closeFileModal} filepath={this.state.pdfToZoom} />:'' }
</div>
)
}
}
You can heavily shorten all this.props and this.state:
getUpdatedData = {this.props.getUpdatedData}
tripid={this.props.tripid}
whichTab={this.props.whichTab}
into
const {getUpdatedData, tripid, whichTab} = this.props
Are you sure length should be different?
You have many setState() calls - it can be modified earlier. Show entire log from 'canvas mounted'.
componentDidUpdate will work as it is. Check this demo on componentDidUpdate.
Demo
I guess, problem lies in somewhere between your component (state or props) while setState.
Can you expose your code base or make a demo with minimal code,that would be help.
for ref, check this: prevState in componentDidUpdate is the currentState?
Related
I am having issues Cannot read properties of undefined (reading 'some')
I am having issues Cannot read properties of undefined (reading 'some') in react when try to search a resort or a hotel Here is the result This is before I hit search button: After hit search button the resort come out correctly: After select filter Activities and hit search button again: Code base from my project: onSubmit for search button: onSubmit() { sessionStorage.remove(ReservationService.APPLIED_POINTS); sessionStorage.remove(ReservationService.BOOKED_RESERVATION); sessionStorage.remove(ReservationService.CONTRACT_TOOL_TIPS); sessionStorage.remove(ReservationService.SELECTED_PREFERENCES); const segments = getUniqueContractSegments(this.state.form); this.reservationService.search(this.state.form, segments).then((results: Results) => { let state: AvailabilityState = this.state; state.filters = results.filters; state.selectedFilters = this.stripInApplicableFilters(results.filters); state.searchResults = results.results; state.showResults = true; state.hideLoader = true; state.loadError = false; state.resultsError = false; state.selectedMonth = state.form.startDate; this.setState(state); }).catch((error: any) => { if (!handle401Error(error)) { let state: AvailabilityState = this.state; state.hideLoader = true; state.resultsError = true; state.searchResultsErrorMessage = error.message ? `${error.message}` : "Unspecified error"; this.setState(state); log.error(`Error: ${JSON.stringify(error)}`); } }); this.setState({hideLoader: false, availability: {form: Object.assign({}, this.state.form)}}); sessionStorage.write(ReservationService.OPS_FORM_SESSION_KEY, JSON.stringify(this.state.form)); } Here is onFilter for filter select in checkbox: onFilterSelect(name: string, item: any) { let selectedFilters: SelectedFilters = {...this.state.selectedFilters}; const selectedFilter = {...selectedFilters[name]}; const idx = selectedFilter.filters.indexOf(item); if (idx > -1) { selectedFilter.filters = selectedFilter.filters.filter((filterOption: string) => filterOption !== item); } else { selectedFilter.filters = [...selectedFilter.filters, item]; // If filter group isn't expanded, expand. // User could be changing filter from room-type pills. if (!selectedFilter.expanded) { selectedFilter.expanded = true; } } selectedFilters[name] = selectedFilter; this.setState({ selectedFilters }); console.log("Filter: ", selectedFilters) } Error:
this error happens when you want to read a property from an object that has no value (is undefined) so there is a simple solution you can put ? before . like Object?.Property it cause when an object is an undefined property does not read may be there : const idx = selectedFilter?.filters?.indexOf(item); if (idx > -1) { selectedFilter.filters = selectedFilter?.filters?.filter((filterOption: string) => filterOption !== item); } else { selectedFilter.filters = [...selectedFilter.filters, item];
How to display the React Axios progress bar?
I want the result screen My componentDidMount () _isMounted = false; componentDidMount() { this._isMounted = true; var page = 0; // 공정 라인 수 //비가동 현황 불러오기 let oprationStatus = () => { axios.get('http://localhost:8080/api/process/FM') .then(response => { var output = response && response.data; //비가동 현황 NonOperationalStatus.data.series[0][0] = output.list[page].nop_000; // 계획 NonOperationalStatus.data.series[0][1] = output.list[page].nop_001; // 재료 NonOperationalStatus.data.series[0][2] = output.list[page].nop_002; // 금형 NonOperationalStatus.data.series[0][3] = output.list[page].nop_003; // 설비 NonOperationalStatus.data.series[0][4] = output.list[page].nop_004; // 사람 NonOperationalStatus.data.series[0][5] = output.list[page].nop_etc; // 기타 }); } //가동율 등등 기본 정보 가져오기 let getProcess = () => { oprationStatus(); axios.get('http://localhost:8080/api/process/FM') .then(response => { var output = response && response.data; if(this._isMounted) { this.setState({ data: output.list[page] }) if(page < output.list.length-1) { page++; } else if(page == output.list.length-1) { page = 0; this.props.history.push('/hdprocess') } setTimeout(getProcess, 1000 * 5); // 매 5초마다 값 가져옴 } }); } getProcess(); } componentWillUnmount() { this._isMounted = false; } This code gets the data from the API server at 5 second intervals and routes it to the next page. What I want is to display a progress icon as the picture above while the asynchronous communication is loading. Let me know if you have a good alternative
Initially use a progress or spinner component. Use it until a valid Response is return from the Axios Function, if a valid Response is attained, change the spinner(progres bar) Component to the actual component
React Native updating data onState variable change
i am trying to execute a function that update the Users data whenever the user come at the end of the Array like so : componentDidUpdate = () => { if (this.state.isLoading == false && this.state.Users.length == this.state.currentIndex) { this.loadUsers() } } Here is the loadUsers() function loadUsers = () => { Users = [ ] var query = firebase.database().ref("users").orderByKey(); query.once("value") .then((snapshot) => { snapshot.forEach((childSnapshot) => { // key will be "ada" the first time and "alan" the second time var key = childSnapshot.key; // childData will be the actual contents of the child var childData = childSnapshot.val(); getFilmDetailFromApi(childData.filmID).then(data => { km = this.getDistance(this.state.userData.latitude, this.state.userData.longitude, childData.latitude, childData.longitude) photo0 = null; photo1 = null; photo2 = null; photo3 = null; photo4 = null; photo5 = null; if(childData.photo[0]) { photo0 = {uri: childData.photo[0]} } if(childData.photo[1]) { photo1 = {uri: childData.photo[1]} } if(childData.photo[2]) { photo2 = {uri: childData.photo[2]} } if(childData.photo[3]) { photo3 = {uri: childData.photo[3]} } if(childData.photo[4]) { photo4 = {uri: childData.photo[4]} } if(childData.photo[5]) { photo5 = {uri: childData.photo[5]} } var filmImage = data.poster_path Users.push({ id: key, uri: photo0, uri1: photo1, uri2: photo2, uri3: photo3, uri4: photo4, uri5: photo5, nom: childData.name, age:childData.age, film: filmImage, description: childData.description, distance: km }) this.setState({ users: key }); }) this.setState({Users: Users}); }); this.setState({isLoading: false}); this.setState({currentIndex: 0}); }); } This work like the tinder cards, when i swipe them all (this.state.Users.length == this.state.currentIndex) become true and it render the loading screen and from there i want to re-run the loadUsers function to get new users but when i run the app i get : "Maximum update depth exceeded".
LoadUsers loads user and sets the state, which causes a rerender of loading screen. Then the loading screen run the LoadUser again trigers the flow again. Edit1: At least, you'd have to have some logic to update the status of loading: Check the modified code: loadUsers = () => { Users = [ ] var query = firebase.database().ref("users").orderByKey(); query.once("value") .then((snapshot) => { snapshot.forEach((childSnapshot) => { // key will be "ada" the first time and "alan" the second time var key = childSnapshot.key; // childData will be the actual contents of the child var childData = childSnapshot.val(); this.setState({isLoading: true}); getFilmDetailFromApi(childData.filmID).then(data => { km = this.getDistance(this.state.userData.latitude, this.state.userData.longitude, childData.latitude, childData.longitude) photo0 = null; photo1 = null; photo2 = null; photo3 = null; photo4 = null; photo5 = null; if(childData.photo[0]) { photo0 = {uri: childData.photo[0]} } if(childData.photo[1]) { photo1 = {uri: childData.photo[1]} } if(childData.photo[2]) { photo2 = {uri: childData.photo[2]} } if(childData.photo[3]) { photo3 = {uri: childData.photo[3]} } if(childData.photo[4]) { photo4 = {uri: childData.photo[4]} } if(childData.photo[5]) { photo5 = {uri: childData.photo[5]} } var filmImage = data.poster_path Users.push({ id: key, uri: photo0, uri1: photo1, uri2: photo2, uri3: photo3, uri4: photo4, uri5: photo5, nom: childData.name, age:childData.age, film: filmImage, description: childData.description, distance: km }) this.setState({ users: key, isLoading: false }); }) this.setState({Users: Users});}); this.setState({currentIndex: 0}); }); }
You are getting this error because you are trying to set state inside a loop and the maximum limit has reached to rerender a view once there is change in state. Try to set Users this.setState({ Users: Users }); once the foreach loop ends(outside of loop). this.setState({ users: key }); this may also need the similar approach.
Showing a loading message until the blob file is downloaded
I am printing a bill as a pdf document after submitting the billing form. The service that is downloading the blob file is as follows. export default [createLogic({ type: reportTypes.REPORT, latest: true, debounce: 2000, process({ MockHTTPClient, getState, action }, dispatch, done) { dispatch(reportActions.queryStart()) let HTTPClient; if (MockHTTPClient) { HTTPClient = MockHTTPClient; } else { HTTPClient = API; } HTTPClient.Post(endPoints.REPORTS_BILL, action.payload.reportOptions) .then( (resp) => { return resp.data }) .then((data) => { dispatch(reportActions.getReportSuccess(data)); var link = document.createElement('a'); link.href = `data:application/octet-stream;base64,${data}`; var today = new Date(); var date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate(); var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds() + ":" + today.getMilliseconds(); var dateTime = date + ' ' + time; var fileName = dateTime + "billing.pdf"; link.download = fileName; link.click(); var base64str = data; var binary = atob(base64str.replace(/\s/g, '')); var len = binary.length; var buffer = new ArrayBuffer(len); var view = new Uint8Array(buffer); for (var i = 0; i < len; i++) { view[i] = binary.charCodeAt(i); } var blob = new Blob([view], { type: "application/pdf" }); var url = URL.createObjectURL(blob); window.open(url); dispatch(reportActions.getReportSuccess(data)) }) .then(() => dispatch(reportActions.queryEnd())) .catch(err => { dispatch(reportActions.getReportFailed()); var errorMessage = "Failed to get prductivity data."; if (err && err.code == "ECONNABORTED") { errorMessage = "Please check your internet connection."; } dispatch( reportActions.getReportFailed({ title: "Error!", message: errorMessage }) ); }) .then(() => done()); } }) ] In the Billing Component following is the method that I am calling the service. printBill = () => { debugger; var reportType = 1; var reportFiltersSet = {}; if (this.billingOptions.length > 0) { this.billingOptions.map(v => { reportFiltersSet[v.name] = v.value; }); } this.props.reportActions.queryStart(); var reportType = 1; //Thiis need to be dynamic. use this => //this.state.reportType var reportFilters = this.state.billingOptions; if ( reportFiltersSet.organization == undefined || reportFiltersSet.department == undefined || reportFiltersSet.division == undefined || reportFiltersSet.billYear == undefined || reportFiltersSet.billMonth == undefined ) { this.setState({ reportContentNull: true, warning: "Error!", errorMessage: "Either department or division reqiured with organization , year and month", negative: true, hidden: false }); this.props.reportActions.getReport({ reportOptions: reportFiltersSet }); var reportDownloadType = this.state.reportType; }; I can download the blob file , when I submit the form without any problem. But in user's perspective it is important to show that the loading state in order to have a better user experince. Therefore can anyone help me out to show a loading message during the submit and loading the blob file?
So the Idea is to start loading as soon as HTTP calls happens and remove it when response is recieved. Simple way would be add a loading variable in state and in render check that variable and show spinner. onClick = () => { this.setState({ loading: true }, () => { Axios.get('/sampelCall') .then(result => this.setState({ loading: false, data: [...result.data], })); }); } render() { const { data, loading } = this.state; return ( <div> <button onClick={this.onClick}> Load Data </button> {loading ? <LoadingSpinner /> : <ResultsTable results={data} />} // if loading in true will show Spinner </div> ); } Note: You need to handle loading variable in all cases (Success/Error) else Spinner will keep on loading.
Can't click on the POI i put on a Forge viewer
Hi i tried a forge viewer with some point of interest to put iot on it. me program is in react. here's my code poiExtension.js here we have all the poi's called by a json (x,y,z): let Autodesk = window.Autodesk; let THREE = window.THREE; // Extension Three.js pour afficher des points d'intérêts sous la forme de billboards de taille fixe faisant face à la caméra // NB: Ne fonctionne bien qu'en mode perspective class POIExtension extends Autodesk.Viewing.Extension { constructor(viewer, options) { super(); this.viewer = viewer; var texture = THREE.ImageUtils.loadTexture("img/icone_pointeur.png"); this.selectedMaterial = new THREE.MeshBasicMaterial( { map: texture, transparent: true, alphaTest: 0.5, color: 0xFF0000 } ); this.defaultMaterial = new THREE.MeshBasicMaterial( { map: texture, transparent: true, alphaTest: 0.5, color: 0x00FF00 } ); this.loaded_poi = []; this.planeGeometry = new THREE.PlaneGeometry(0.6, 1, 1, 1); this.spriteScaleFactor = 0.8; this.spriteAltitude = 15.0; } load () { let self = this; this.viewer.addEventListener(Autodesk.Viewing.CAMERA_CHANGE_EVENT, (event) => { this.animate(self); } ); return true } unload () { return true } setSettings(settings) { const scale = 1.0 / 255.0; this.selectedMaterial.color.setRGB( settings.selectedPointColor[0] * scale, settings.selectedPointColor[1] * scale, settings.selectedPointColor[2] * scale); this.defaultMaterial.color.setRGB( settings.defaultPointColor[0] * scale, settings.defaultPointColor[1] * scale, settings.defaultPointColor[2] * scale); this.spriteScaleFactor = settings.spriteScaleFactor; this.spriteAltitude = settings.spriteAltitude; } clearAllPOI () { this.loaded_poi.map((poiParticle) => { this.viewer.impl.scene.remove( poiParticle.mesh ); }); this.loaded_poi = []; } createPOI (poi, isSelected) { let poiParticle = { poi: poi, mesh: new THREE.Mesh(this.planeGeometry, isSelected === true ? this.selectedMaterial : this.defaultMaterial) } this.loaded_poi.push(poiParticle); poiParticle.original_position = { x: poi.x, y: poi.y, z: poi.z } poiParticle.mesh.position.set(poi.x, poi.y, this.spriteAltitude); this.viewer.impl.scene.add(poiParticle.mesh); this.viewer.impl.sceneUpdated(true); this.animate(); } animate() { // THIS IS A HUGE HACK REQUIRED BECAUSE SOME STATE IN FORGE I'SNT SET CORRECTLY IN SOME BROWSER if (this.hacked === undefined) { this.viewer.toolbar._controls[1]; let menu_1 = this.viewer.toolbar._controls[2]; if ((menu_1 !== undefined) && (menu_1._controls!== undefined)) { let menu_2 = menu_1._controls[0]; if ((menu_2 !== undefined) && (menu_2.subMenu !== undefined) && (menu_2.subMenu._controls !== undefined)) { menu_2.subMenu._controls[2].onClick(); this.hacked = true; } } } // END HACK this.loaded_poi.map((poiParticle) => { var vec = new THREE.Vector3(); var defaultDepth = 10; poiParticle.mesh.scale.x = poiParticle.mesh.scale.y = poiParticle.mesh.scale.z = this.spriteScaleFactor * vec.setFromMatrixPosition( poiParticle.mesh.matrixWorld ).sub( this.viewer.impl.camera.position ).length() / defaultDepth; poiParticle.mesh.position.set(poiParticle.original_position.x, poiParticle.original_position.y, poiParticle.original_position.z ); poiParticle.mesh.quaternion.copy( this.viewer.impl.camera.quaternion ); this.viewer.impl.scene.updateMatrixWorld(true); }); } } export default POIExtension; And here's is my poiList.js (the clickable list on the right): import React, { Component } from 'react'; import './poiList.css'; // Composant react affichant la liste des points d'intérêts // C'est ce composant qui communique avec l'extension POI class PoiList extends Component { constructor(props) { super(props); this.state = { poi: [], selectedPoi: undefined, settings: { defaultPointColor: [61, 183, 255], selectedPointColor: [37, 27, 255], defaultPointTransparancy: 0.4, spriteScaleFactor: 0.8, //altitude par défaut spriteAltitude: 15.0 } }; } componentDidMount() { fetch('/settings') .then(response => { if (!response.ok) { console.log(`status ${response.status}`); throw new Error(`status ${response.status}`); } return response.json(); }) .then(json => { this.setState({ settings: json }); }) .catch(e => { console.log(`Settings call failed: ${e}`); this.setState({ message: `Settings call failed: ${e}` }); }) fetch('/poi') .then(response => { if (!response.ok) { console.log(`status ${response.status}`); throw new Error(`status ${response.status}`); } return response.json(); }) .then(json => { this.setState({ poi: json.poi }); }) .catch(e => { console.log(`POI call failed: ${e}`); this.setState({ message: `POI call failed: ${e}` }); }); } render() { if(this.props.poiExtension !== undefined) { this.props.poiExtension.clearAllPOI(); this.props.poiExtension.setSettings(this.state.settings); } let self = this; let poiList = []; let index = 0; this.state.poi.map((poi) => { if(this.props.poiExtension !== undefined) { this.props.poiExtension.createPOI(poi, this.state.selectedPoi === poi); } let colorState = index % 2 === 1 ? "lightgrey" : ""; colorState = this.state.selectedPoi === poi ? "selected" : colorState; let classC = "poiEntry " + colorState; let poiItem = ( <div className={classC} key={index} onClick={() => { self.setState({ selectedPoi: poi, }); }}> {poi.type} ({poi.x}, {poi.y}, {poi.z}) </div> ); index++; poiList.push(poiItem); }) return( <div className="fullscreen"> <div className="poiTitle">BATIMENT E17</div> <div className="poiList"> { poiList } </div> </div> ); } } export default PoiList; i don't know how to do it....then if someone can help me i'll be very happy :)
Looks like your issue does not really has to do with Forge or Viewer.js but... If by "can't click on POIs" you meant when you clicked on a POI's DIV nothing happens (no highlight visible) then Redux serialize your states so the way you test whether the current selectedPOI is selected won't work - use a serializable key (ID string etc) to identify your POIs: colorState = this.state.selectedPoi.id === poi.id ? "selected" : colorState;