Reputation: 551
I've created a login system with React which stores a session when the user logs in. When the page is reloaded, I have added a function which should check if the session exists and then either setState()
to true
or to false
.
As I'm new to React, I'm not sure how to execute this function. Please see my code below for App.js:
import React from 'react';
import './css/App.css';
import LoginForm from "./LoginForm";
import Dashboard from "./Dashboard";
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
renderLoginForm: true
};
this.handleLoginFormMount = this.handleLoginFormMount.bind(this);
}
handleLoginFormMount() {
this.setState({
renderLoginForm: false
});
}
// Check session function.
checkSession() {
fetch('/check-session', {
credentials: 'include'
})
.then((response) => {
return response.json();
})
.then((sessionResult) => {
if (sessionResult.username) {
console.log('false');
this.setState({
renderLoginForm: false
});
} else {
console.log('true');
this.setState({
renderLoginForm: true
});
}
})
.catch((error) => {
console.log('Error: ', error);
});
}
render() {
checkSession();
return (
<div className="App">
{this.state.renderLoginForm ? <LoginForm mountLoginForm={this.handleLoginFormMount} /> : null}
{this.state.renderLoginForm ? null : <Dashboard />}
</div>
);
}
}
export default App;
Having checkSession()
in this position outputs the following in the console when loading the page:
Line 50: 'checkSession' is not defined no-undef
If I put the function outside of the class App extends React.Component {}
, then it tells me that I cannot set the state of undefined.
Upvotes: 9
Views: 73061
Reputation: 4501
Functional Component: In my case I wanted my code to run before component renders on the screen. useLayoutEffect
is a hook provided by React for this exact purpose.
import React, { useLayoutEffect } from "react";
...
const App = () => {
useLayoutEffect(() => {
//this runs before render
}, []);
}
Read More: https://reactjs.org/docs/hooks-reference.html#uselayouteffect
Upvotes: 18
Reputation: 11
export default function App() {
const initialRenderRef = useRef(true);
if (initialRenderRef.current){
initialRenderRef.current = false;
// your code here, executes before render
}
return (
<div className="App">
My super app!
</div>
);
}
Your code will run once, at first render. initialRenderRef
prevent code to run twice or more.
Upvotes: 0
Reputation: 4035
useLayoutEffect is NOT correct way to execute code before render. Quote from react.dev
useLayoutEffect is a version of useEffect that fires before the browser repaints the screen.
repaints does not mean that it'll trigger before the first render.
In Class components, componentWillMount will be executed before the render. The complete match of componentWillMount is not completely exist in functional components.
Possible solution is, put a boolean flag, make it true in useEffect (with empty dependency array), if it's false, that means it's before render.
export default function App() {
const isMounted = useRef(false)
if (!isMounted.current){
// your code here, executes before render
}
useEffect(() =>{
// Initial render has been completed
// make the flag true
isMounted.current = true
},[])
return (
<div className="App">
</div>
);
}
This way, you won't re-render the component (since no setState() triggers exist).
Upvotes: 3
Reputation: 1074208
Having
checkSession()
in this position outputs the following in the console when loading the page:Line 50: 'checkSession' is not defined no-undef
That's because it's a method, but you're calling it like a freestanding function. The call should be this.checkSession();
. But keep reading.
Separately:
The render
function must be pure, it cannot have side-effects like changing state. Instead, put any side-effects code in componentDidMount
; from the documentation for that lifecycle method:
If you need to load data from a remote endpoint, this is a good place to instantiate the network request.
Be sure that your component renders correctly for the original state (before the session check), as well as for the updated state (after the session check).
More about lifecycle methods and such in the documentation.
Alternately, if this component can't do anything useful without the session, you might move the session check to its parent component, and have the parent only render this child component when it has the session check results.
Upvotes: 8