react unmouting when navigate away - url-routing

i have this react component which works so will when i render it
var Postlist = React.createClass({
getInitialState: function () {
socket.on("new",this.Updatepost);
return {posts: [], hasMore: true, onView: 5};
},
componentWillMount: function () {
this.state.posts.push(this.props.newposts);
this.setState({posts: this.props.newposts});
},
$.ajax({
url: 'load_posts.php',
dataType: 'json',
success: function (data) {
var x = data;
React.render(<Postlist newposts={x} />,document.getElementById("main"));
}.bind(this),
error: function (xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
but iam using history api to navigate between pages
so how can i unmount and remount react component when navigating and how to unmounting it outside react code

i don't think you can do that , react handles the lifecycle of a component by itself , so i think the way to work around this should be something like actually save the previous state within the browser history .. so when you go back and forth you can tell react that should update by pushing a "new" state

Related

Call an API method via React Redux on Browser close using 'beforeunload' event listener

I have a React App and I want there to be a DELETE call to an API method when a user closes the browser. I have therefore added this into the App.js:
import myReduxAction from "./Redux/Actions/admin/superAdminActions";
componentDidMount() {
...
this.setupBeforeUnloadListener();
}
setupBeforeUnloadListener = () => {
window.addEventListener("beforeunload", (ev) => {
this.methodToCallBeforeUnload();
debugger;
});
};
methodToCallBeforeUnload= () => {
myReduxAction.myActionMethodSynchronous();
}
When the browser is closed, I can enter a debugger into the above code and it seems to run through fine. However, I notice that the API method is not being hit. My Action method looks something like this:
const myActionMethodSynchronous = () => {
debugger;
return function () {
debugger;
try {
myApi.myAPIMethodSynchronous();
} catch (error) {
// Code to handle errors
}
};
};
And the actual call to the API:
const myAPIMethodSynchronous= () => {
debugger;
return axios.delete(`/MyAPI/myapimethodname/`);
};
I have added 2xdebugger; to the Action Method. One above the return function and another below. The first one gets hit, however the second one (and the one inside the api call) are never hit.
Am I missing something obvious here. I also have a button that is wired up to this Action Method and that seems to work fine. I only seem to have this problem when trying to initiate it from closing the browser.
What the browser/device do you use? onbeforeunload and onunload are not supported in all browsers. For example, this code:
window.onbeforeunload = function() {
fetch('/api/some_method1', {
method:'GET',
headers: {
'Content-Type': 'application/json'
},
})
}
window.onunload = function () {
fetch('/api/some_method2', {
method:'GET',
headers: {
'Content-Type': 'application/json'
},
})
}
works fully in Chrome and Opera (I got both requests), in Safari I got only onbeforeunload, and it seems that it is not working on iOS.

React: request to API trigger two times the then block, the request is sended twice

I know that the API call must be not placed into render method, but this is just for testing:
I have the below code. When i call the fetchData into the render method the 'Send request ...' message is printed once and the respnse printed twice!?
Output:
Page 1 ... rendering
Send request ...
{data: "Hello there", status: 200, statusText: "", headers: {…}, config: {…}, …}
{data: "Hello there", status: 200, statusText: "", headers: {…}, config: {…}, …}
Why this happens? I have checked also the network tab, and both the request is GET and not a OPTIONS related to CORS.
Also on the server the GET method handler has executed twice.
import React from 'react';
const axios = require('axios').default;
class Page1 extends React.Component {
// componentDidMount() {
// this.fetchData()
// }
fetchData() {
console.log('Send request ...');
axios.get('http://localhost:8080/api/hello/')
.then(function (response) {
console.log(response);
return response.data;
})
.catch(function (error) {
console.log(error);
});
}
render() {
console.log('[Page 1] render called')
this.fetchData();
return (<h1>Hello from Page 1. </h1>);
}
}
export default Page1;
When your application is wrapped in <React.StrictMode> your components will render twice in development environments. This is for error/warning detection. Strict mode will intentionally invoke the following class component functions twice: constructors, the render method, and the shouldComponentUpdate methods. Read more about strict mode in the docs.

react lifting state up after login verified

I'd like to create component - - so that only authorised users can access it. the idea is that after receiving response 200 from backend in my Login component (which is a child component) I would somehow use authed:true as props in parent component. I understand this instructions https://reactjs.org/docs/lifting-state-up.html and also used similar procedure on other components. However, in this case, I am getting the error:
TypeError: this.props.authAfter200 is not a function
at Login.handleSetAuthAfterVerified200 (AuthExample.js:325)
at AuthExample.js:350
at <anonymous>
The problem is I am not able to define function as a prop in my child component.
This is the function in my parent component that should get called as a prop.
setAuthToTrue=() => {
this.setState({authed:true})
}
but I never get to here.
This is how I have defined my Route router in AuthExample(parent) component - using react-router-with-props for that:
<PrivateRoute
exact
path="/private"
redirectTo="/login"
component={DailyNewsForUOnly}
text="This is a private route"
authAfter200={this.setAuthToTrue}
authed={this.state.authed}
/>
this is the part in my child component - Login.js where I should be able to define function on my props to pass to the parent component - but I just cannot:
handleSetAuthAfterVerified200() {
//this.setState({authed:true})
this.props.authAfter200()
}
verifyToken() {
let request = {
method: "post",
url: "https://xxxxxx/xxxx/verify/",
data: {
user: this.state.email,
token: this.state.token
},
withCredentials: true
};
console.log("request to verify");
console.log(request);
this.setState({ requestInMotion: true });
axios(request)
.then(response => {
console.log("response from verify", response);
if (response.status === 200) {
this.handleSetAuthAfterVerified200()
this.setStateAfterVerified200()
}
})
.catch(error => {
console.log(error);
this.setState({ requestInMotion: false, validationState: "error" });
console.log(
"this.state in the error part of response in verify",
this.state
);
});
}
i would suggest u to try to add debuggers in
react-router-with-props/PrivateRoute.js and in
react-router-with-props/renderMergedProps.js
and check if your props are actually being passed on properly.
he is doing very simple job of either allowing react to render your component or to redirect to url provided as prop.
I would suggest you rather use HigherOrderComponents or OnEnter route hook to handle these situations than a third party component.

ReactJs failing to bind data object

I'm new to ReactJs and I'm trying to bind a http response to the DOM, but I can't get it to work. Im using componentDidMount to execute the api call. Any help will be much appreciated, please see code below.
var testStuff="First State";
var Test = React.createClass({
loadTestData: function () {
$.ajax({
url: "http://localhost:64443/api/articles/apitest",
type: 'GET',
cache: false,
dataType: 'json',
success: function (response) {
console.log(response);
testStuff= response;
},
error: function (error) {
alert(error);
}
});
},
componentDidMount() {
this.loadTestData();
},
render() {
console.log(this.testStuff);
return (
<div onClick={this.loadTestData}>
{testStuff}
</div>
);
}
});
ReactDOM.render(
<Test />,
document.getElementById('content')
);
The onClick seems to be working, but its almost like the componentDidMount only gets executed after the page is rendered.
You need to properly update the component state in the AJAX success handler: this.setState({ testStuff: data })
Then you will be able to access it in render using this.state.testStuff.
componentDidMount indeed only runs after component has been mounted. You will also need to represent the UI state where the requests is still ongoing (this.state.testStuff will be undefined at that point).

Acces this.state variables in React

I have the following code in react :
getInitialState: function() {
var state= {
data: {}
};
fetch(this.props.dataurl)
.then(function(response) {
return response.json();
})
.then(function(result) {
this.setState({data:result});
}.bind(this));
return this.state;
},
componentDidMount: function() {
console.log(this);
console.log(this.state);
}
So in the getInitialState function I initialize the state variable data with results from fetch and then I want to access the data variable in the second function componentDidMount.
The problem I have is that this.state returns the data object empty but when I try to log this I'm getting the data variable with the data in it.
So why I'm having this behavior and how can I solve it?
componentDidMount does not guarantee that the async fetch has been completed.
You should define componentDidUpdate that will be called when the state has been changed, so that you can do anything with that new data.
componentDidUpdate(object prevProps, object prevState)
See React Lifecycle.

Resources