如何正确摆脱 UNSAFE_componentWillMount
How to properly get rid of UNSAFE_componentWillMount
对于我从其他开发人员那里继承的 React 应用程序,其中一个页面包括:
import { getLogUser } from "../../appRedux/actions/authAction";
constructor(props) {
super(props);
this.state = {
user: null,
};
}
UNSAFE_componentWillMount() {
let user = getLogUser();
this.setState({ user });
// user state is used inside the render part
}
componentDidMount = () => {
let { username } = getLogUser();
// ... username is used inside some logic within the componentDidMount method.
我想摆脱 UNSAFE_componentWillMount
方法。
- 如果我在
constructor
中使用 user: getLogUser()
,我可以删除 UNSAFE_componentWillMount
部分吗?
- 如果那确实是正确的方法,那我不也应该这样做吗?
替换里面的
let { username } = getLogUser();
componentDidMount
和 let { username } = this.state.user
?
首先,让我先解释一下什么是UNSAFE_componentWillMount
来自 defination
UNSAFE_componentWillMount() is invoked just before mounting occurs. It is called before render(), therefore calling setState() synchronously in this method will not trigger an extra rendering.
所以意味着UNSAFE_componentWillMount()
会在render()
之前被调用(组件还没有在UI上)。这与在 render()
之后调用的 componentDidMount()
完全相反
要更深入地了解 React 团队为何要将其 UNSAFE
作为弃用函数,您可以查看 this RFC.
跟进您的问题
Can I remove the UNSAFE_componentWillMount part if I use user: getLogUser() inside the constructor?
在 constructor
中调用函数的好处与 UNSAFE_componentWillMount
类似,可确保您的数据在呈现触发器之前可用。
所以我同意你的情况,只要它不是异步函数(比如 async/await
)你就可以这样做
constructor(props) {
super(props);
this.state = {
user: await getLogUser(), //YOU CANNOT DO THIS WAY
};
}
这是正确的方法
constructor(props) {
super(props);
this.state = {
user: getLogUser(), //no asynchronous call
};
}
那么如果getLogUser()
是异步的呢? componentDidMount
派上用场了。它将在第一次呈现后触发,但您可以根据需要等待数据,并且不会阻塞 UI 的交互(或者您可以显示正在加载 UI )
componentDidMount = async () => {
const user = await getLogUser()
setState({ user })
}
render() {
//show loading if `user` data is not populated yet
const { user } = this.state
if(!user) {
return <div>Loading</div>
}
}
If that is indeed the correct way to do it, shouldn't I then also replace let { username } = getLogUser(); inside componentDidMount with let { username } = this.state.user?
是的,的确如此。如果您已经在 constructor
中填充了 user
状态,则可以执行此操作,但您需要确保您的函数将在短时间内执行。如果您的函数调用时间过长,将导致 UI 由于渲染受阻而出现问题。
//trigger before first rendering
constructor(props) {
super(props);
this.state = {
user: getLogUser(), //no asynchronous call
};
}
//trigger after first rendering
componentDidMount = () => {
const { username } = this.state.user;
}
对于我从其他开发人员那里继承的 React 应用程序,其中一个页面包括:
import { getLogUser } from "../../appRedux/actions/authAction";
constructor(props) {
super(props);
this.state = {
user: null,
};
}
UNSAFE_componentWillMount() {
let user = getLogUser();
this.setState({ user });
// user state is used inside the render part
}
componentDidMount = () => {
let { username } = getLogUser();
// ... username is used inside some logic within the componentDidMount method.
我想摆脱 UNSAFE_componentWillMount
方法。
- 如果我在
constructor
中使用user: getLogUser()
,我可以删除UNSAFE_componentWillMount
部分吗? - 如果那确实是正确的方法,那我不也应该这样做吗?
替换里面的
let { username } = getLogUser();
componentDidMount
和let { username } = this.state.user
?
首先,让我先解释一下什么是UNSAFE_componentWillMount
来自 defination
UNSAFE_componentWillMount() is invoked just before mounting occurs. It is called before render(), therefore calling setState() synchronously in this method will not trigger an extra rendering.
所以意味着UNSAFE_componentWillMount()
会在render()
之前被调用(组件还没有在UI上)。这与在 render()
componentDidMount()
完全相反
要更深入地了解 React 团队为何要将其 UNSAFE
作为弃用函数,您可以查看 this RFC.
跟进您的问题
Can I remove the UNSAFE_componentWillMount part if I use user: getLogUser() inside the constructor?
在 constructor
中调用函数的好处与 UNSAFE_componentWillMount
类似,可确保您的数据在呈现触发器之前可用。
所以我同意你的情况,只要它不是异步函数(比如 async/await
)你就可以这样做
constructor(props) {
super(props);
this.state = {
user: await getLogUser(), //YOU CANNOT DO THIS WAY
};
}
这是正确的方法
constructor(props) {
super(props);
this.state = {
user: getLogUser(), //no asynchronous call
};
}
那么如果getLogUser()
是异步的呢? componentDidMount
派上用场了。它将在第一次呈现后触发,但您可以根据需要等待数据,并且不会阻塞 UI 的交互(或者您可以显示正在加载 UI )
componentDidMount = async () => {
const user = await getLogUser()
setState({ user })
}
render() {
//show loading if `user` data is not populated yet
const { user } = this.state
if(!user) {
return <div>Loading</div>
}
}
If that is indeed the correct way to do it, shouldn't I then also replace let { username } = getLogUser(); inside componentDidMount with let { username } = this.state.user?
是的,的确如此。如果您已经在 constructor
中填充了 user
状态,则可以执行此操作,但您需要确保您的函数将在短时间内执行。如果您的函数调用时间过长,将导致 UI 由于渲染受阻而出现问题。
//trigger before first rendering
constructor(props) {
super(props);
this.state = {
user: getLogUser(), //no asynchronous call
};
}
//trigger after first rendering
componentDidMount = () => {
const { username } = this.state.user;
}