React native - Invalid state update warning - reactjs

The following code produces a Warning 'Cant perform a React State update in an unmounted component. This is a no-op, but it indicated a memory leak in your application..'
I'm new to RN - working my way through my first build - I cant understand why this error is being produced as I am not calling any stae changes until componentDidMount - can anyone offer any tips please?
Class CheckIn extends React.Component {
constructor(props) {
super(props);
this.state = {
venue: undefined,
checkinTime:0,
currentLocation:null,
};
}
getCurrentCoordinates = () => {
navigator.geolocation.getCurrentPosition(
position => {
const currentLongitude = JSON.stringify(position.coords.longitude);
const currentLatitude = JSON.stringify(position.coords.latitude);
const currentLocation = currentLatitude + ',' + currentLongitude;
this.setState({ currentLocation });
this.getCurrentTime();
},
error => Alert.alert(error.message),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
);
};
minutes_with_leading_zeros=(dt)=>
{
return (dt.getMinutes() < 10 ? '0' : '') + dt.getMinutes();
}
getCurrentTime = () => {
const dt = new Date();
const dtcur = dt.getHours() +':' +this.minutes_with_leading_zeros(dt);
this.setState({
checkinTime: dtcur,
});
};
componentDidMount(){
this.getCurrentCoordinates();
this.getCurrentTime();
}

Related

react can not show console log variable

why my log not showing anything ? is ths because the variable isLoading state ?
my code :
function getColumns(data) {
const columns = [];
const sample = data[0];
console.log("theSample" + sample);
and i call it from here :
class App extends React.Component {
constructor() {
super();
this.state = { isLoading: true };
if (this.state.isLoading === false) {
//const data = getData();
const data = this.state.dataExt;
// console.log(data);
const columns = getColumns(data);
this.state = {
data,
columns,
visible: false
};
}
}
Because, you only call getColumns when this.state.isLoading === false, and the initial value of your isLoading state is true. Therefore, unless you update your isLoading state, getColumns wouldn't be called and your log wouldn't show up.

Why is not entering componentDidUpdate()?

Hello I'm trying to test a state that is changed in the componentDidUpdate but is not enetering.
Code
componentDidUpdate (newProps) {
const { dataSource } = newProps
// set value for nextButtonDisabled in first results async load
if (dataSource.length) {
const newPaginationInfo = Object.assign({}, this.state.paginationInfo)
newPaginationInfo.nextButtonDisabled = dataSource.length <= this.pageSize
this.setState({ paginationInfo: newPaginationInfo }) /* eslint-disable-line react/no-did-update-set-state */
}
}
State
this.state = {
paginationInfo: {
currentPage: 0,
nextButtonDisabled: true
}
}
And the test
it('should set nextButtonDisabled to false when gets new props.datasource if datasource length <= 20', () => {
const component = shallow(<VehicleHistoryTable {...makeProps()} />)
component.setProps({ dataSource: createDataSourceMock(3) })
expect(component.instance().state.paginationInfo.nextButtonDisabled).toEqual(true)
})
The function createDataSourceMock() creates an array of numbers, in this case 3 rows.
Any suggestions?
P:S I'm trying to migrate to React 17

how to update state with in method in reactjs

There is a state and i want to update this state with in a function.
In function i declared a variable and i want to update state with this variable.
this.state = {
RequestData : [],
searchopen : false,
capturedImage : ""
}
screenShot = () => {
html2canvas(document.body).then(function(canvas) {
document.body.appendChild(canvas);
// Get base64URL
var base64URL = canvas.toDataURL('image/jpeg').replace('image/jpeg', 'image/octet-stream');
});
this.setState({capturedImage: base64URL})
}
You need to put setState in function that get base64URL and bind your screenShot function to use this.setState:
// constructor
constructor(props) {
super(props);
this.state = {
RequestData: [],
searchopen: false,
capturedImage: ""
}
this.screenShot = this.screenShot.bind(this);
}
screenShot = () => {
html2canvas(document.body).then(function (canvas) {
document.body.appendChild(canvas);
// Get base64URL
var base64URL = canvas.toDataURL('image/jpeg').replace('image/jpeg', 'image/octet-stream');
this.setState({ capturedImage: base64URL })
}.bind(this)); // bind here also
}
The problem here is you are doing the state update outside the callback function. Since this is a asynchronous task, your method will not work. Try this:
screenShot = () => {
html2canvas(document.body).then(function(canvas) {
document.body.appendChild(canvas);
// Get base64URL
var base64URL = canvas.toDataURL('image/jpeg').replace('image/jpeg', 'image/octet-stream');
this.setState({capturedImage: base64URL})
});
}
Not pretty but should work
this.state = {
RequestData : [],
searchopen : false,
capturedImage : ""
}
screenShot = () => {
var setState = newStore => this.setState((state, props) => ({ ...newStore })); // define the function outside
html2canvas(document.body).then(function(canvas) {
document.body.appendChild(canvas);
// Get base64URL
var base64URL = canvas.toDataURL('image/jpeg').replace('image/jpeg','image/octet-stream');
setState({capturedImage: base64URL}) // use here
});
}

React "this hasn't been initialised - super() hasn't been called " only in Build

I'm working on a react app base con create-react-app, the app works well on dev server but when I run the build something happen and the app not working.
I use a HOC with some function as context, the function declared in the context (HOC) not working because this is not declared.
Everything work fine on dev, if for test before the build I comment
this.getProducts();
on componentDidMount the problems move forward on the next function that use this.
Someone can help me? Thanks in advance.
const GlobalContext = React.createContext()
class GlobalProvider extends React.Component {
constructor(props) {
super(props)
this.loadingToggle = ( status = null, where = '' ) => {
// enable and disable loading
}
this.loginFunction = (e, utente_id, password) => {
// rest api login
}
this.logoutFunction = () => {
// logout
}
this.getProducts = () => {
this.forceUpdate();
this.loadingToggle(true, "getProducts");
// HERE THE PROBLEMS
var _this = this;
axios.post(Config.apiBaseUrl + '/users/products', {
token: localStorage.getItem('token')
})
.then( (response) => {
if (response.data.success !== true ){
// user not exist
}else{
// populate user data
// HERE I USE _this
}
})
.catch(function (error) {
// catch error
});
}
this.cartVariation = (id, qty, minQty = 0) => {
// cart action
}
this.sendOrder = (addressId) => {
// send order
}
this.state = {
isAuth: false,
loginFunction: this.loginFunction,
logoutFunction: this.logoutFunction,
cartVariation: this.cartVariation,
removeCart: this.removeCart,
cart: null,
forceUpdate: this.forceUpdate,
lastUpdate: new Date().getTime(),
cartCount: JSON.parse(localStorage.getItem("mf-cart")) !== null ? Object.keys( JSON.parse(localStorage.getItem("mf-cart"))).length : 0,
loadingToggle: this.loadingToggle,
loading: false,
store : {
mf_product_list : [],
mf_categories : [],
mf_users : [],
mf_users_formatted : [],
mf_backorders : [],
mf_backorders_list : [],
mf_address : []
},
sendOrder: this.sendOrder
}
}
componentDidMount () {
if (localStorage.getItem('token') !== null && localStorage.getItem('token-timestamp') !== null ){
this.setState({isAuth : true});
}
this.getProducts();
}
render() {
return (
<GlobalContext.Provider
value={{
isAuth: this.state.isAuth,
authToken: null,
loginFunction: this.state.loginFunction,
logoutFunction: this.state.logoutFunction,
cartVariation: this.state.cartVariation,
removeCart: this.state.removeCart,
cart: null,
forceUpdate: this.state.forceUpdate,
lastUpdate: this.state.lastUpdate,
cartCount: this.state.cartCount,
loading: this.state.loading,
store: this.state.store,
sendOrder: this.sendOrder
}}
>
{this.props.children}
</GlobalContext.Provider>
)
}
}
const GlobalConsumer = GlobalContext.Consumer
export { GlobalProvider, GlobalConsumer }
Change the function binding from Class properties
this.getProducts = () => {
// ...
}
to bind it in the constructor (ES2015)
constructor(props) {
// ...
this.getProducts = this.getProducts.bind(this);
}
More information about function binding is here.

How to stop the state variable to be overwritten from previous value in reactjs?

i am storing the data got from server in a state variable. It works fine if i open items having large data display correct information. however after opening item with no data available for it displays previous item value.
consider the scenario,
item 1 has no data, item2 has large data.
open item1 displays no data for it.
now open item2 displays data for it (which is large)
now open item1 displays item2 data instead of showing no data.
Not sure where i am going wrong.
Below is the code,
class ItemDetails extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
item_info: null,
item_info_loading: false,
};
componentDidMount() {
this.unmount = new Promise((resolve) => { this.on_unmount =
resolve;});
this.load_item_info();
this.unlisten_path_change = this.props.history.listen((location) =>
{this.handle_path_change(location.pathname);});
}
componentDidUpdate(prevProps, prevState) {
if (prevProps.item_id !== this.props.item_id) {
this.setState({item_info: null}, this.load_item_info);}
}
componentWillReceiveProps(nextProps, nextState) {
if(nextProps.item_id !== this.props.item_id) {
this.setState({item_info: null}, this.load_item_info);
}}
componentWillUnmount() {
this.on_unmount();
this.unlisten_path_change();
}
load_item_info = () => {
const file_name = 'item_info.json';
this.setState({item_info_loading: true});
client.get_item_file(this.props.model_id, file_name, 'json',
this.unmount).finally(() => this.setState({item_info_loading: false}))
.then((request) => {
this.setState({item_info: request.response})
})};
render () {
<ItemInfoTool
item_info={state.item_info}
item_info_loading={this.state.item_info_loading}/>}}
export default class ItemInfoTool extends React.Component {
state = {
open_item_data: null,};
componentDidMount() {
this.set_open_item_data();
}
componentDidUpdate(prevProps) {
if (prevProps.selected_id !== this.props.selected_id) {
this.set_open_item_data();
}
}
set_open_item_data = () => {
if (!this.props.item_info) {
return;
}
if (this.props.selected_id === this.empty_id) {
this.setState({open_item_data: null});
return;
}
let open_item_data = {
info: [],
values: [],
};
const item_info = this.props.item_info;
for (let i=0, ii=item_info.length; i < ii; i++) {
if (item_info[i].somekey.includes(this.props.selected_id)) {
const info = item_info[i].info;
const values = object_info[i].values;
open_item_data = {
info: typeof info === 'string' ? info.split('\r\n') : [],
values: values ? values : [],
};
break;
}
}
this.setState({open_item_data:open_item_data);
};}
export function get_item_file(item_id, file_name, response_type,
on_progress, cancel) {
const local_override_defined = item_files[item_id] &&
item_files[item_id][file_name];
if (local_override_defined) {
const file = item_files[item_id][file_name];
const reader = new FileReader();
return new Promise(resolve => {
if (response_type === 'blob') {
resolve({response: file});
} else {
reader.onload = () => {
if (response_type === 'json') {
resolve({response: JSON.parse(reader.result)});
} else {
resolve({response: reader.result});
}};
reader.readAsText(file);}});}
return new Promise((resolve, reject) => {
item_file_get_url(item_id, file_name).then(({response}) => {
const request = new XMLHttpRequest();
request.addEventListener('progress', on_progress);
request.open('GET', response.url);
request.responseType = response_type;
send_request(request, undefined, cancel,
response.url).then(resolve).catch(reject);})});}
Could someone help me solve it. Thanks. i doubt there is some asynchronous requests happening.
You need to clear data while closing operation

Resources