componentDidMount() {
const user = auth.getCurrentUser();
this.setState({ user });
}
I have this code, I think this.setState({ user });
takes a little time, if I want to do some checks immidetly like
<Route
path="/foo"
render={props =>
this.state.user ? (
<Bar {...props} />
) : (
<Redirect to="/login" />
)
}
/>
when refreshing the page the user at the beginning is always null. what is the proper solution? do I need to set state at constructor
? or did I do something wrong?
My account got blocked by some down votes questions, the funny thing is I have to re-edit them, even though I already have the accepted answer.I do not understand what's the point to do this.I am so frustrated by this stackoverflow system.
Now, I basically can do nothing but keep editing my questions, and they have all been answered. This is ridiculous !!!
Yes, you should initialise your state in the constructor.
See the React docs example :
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
when refreshing the page the user at the beginning is always null
@Shubham Khatri did explain it really well, in short, just because the render()
function is called before the componentDidMount()
, hence, the user
is always null.
Take a look at this: React lifecycle methods diagram
And as you can see that, the proper place for setState
should be the contructor()
cuz it's called before the render()
.
However, for api calls why
componentDidMount
is the better place? why we do not do all set up inconstructor
?
I know you're talking about this: https://reactjs.org/docs/faq-ajax.html . The document does say that: You should populate data with AJAX calls in the componentDidMount
lifecycle method. This is so you can use setState
to update your component when the data is retrieved.
However,in another place , they say:
You may call
setState()
immediately incomponentDidMount()
. It will trigger an extra rendering, but it will happen before the browser updates the screen. This guarantees that even though therender()
will be called twice in this case, the user won't see the intermediate state. Use this pattern with caution because it often causes performance issues. In most cases, you should be able to assign the initial state in theconstructor()
instead. It can, however, be necessary for cases like modals and tooltips when you need to measure a DOM node before rendering something that depends on its size or position.
...and also for the case that you need to authenticate because this process depends on the value of the user
( as your design).
The problem in your code is that, componentDidMount
is called after render and by the time your user details are fetched and stored in state, your component is ready to redirect to /login
since user wan't available. To solve this issue, you need to fetch user
details before the initial render and hence constructor
is the ideal place to do it
constructor(props) {
super(props);
this.state = {
user: auth.getCurrentUser()
}
}
The state goes inside the constructor, but only if you need a constructor (eg:to initialize flags). If you don't need a constructor you can just initialize the state outside:
class MyComponent extends Component {
state = { myState = [] }
render() {
const { myState } = this.state
return (...)
}
}
You should use the constructor() to initiate state, componentDidMount() for call functions and componentWillReceiveProps() for setState.
constructor(props) {
super(props);
this.state = {
firstName: "",
lastName: ""
};
}
componentDidMount() {
this.props.userProfile();
}
componentWillReceiveProps(nextProps, prevProps) {
this.setState({
firstName: nextProps.user.firstName,
lastName: nextProps.user.lastName
});
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.