Hem*_*ari 28 javascript reactjs react-native react-hooks
基本上我们componentDidMount()在React类组件中的生命周期方法中进行API调用,如下所示
componentDidMount(){
//Here we do API call and do setState accordingly
}
Run Code Online (Sandbox Code Playgroud)
但是在React v16.7.0中引入了钩子之后,就没有更多的类组件了.
我的查询是,我们究竟需要在带有钩子的功能组件中进行API调用?
我们有类似的方法componentDidMount()吗?
Yan*_*Tay 49
是的,有一个类似的(但不一样!)替换为componentDidMount钩子,它是useEffect钩子.
其他答案并没有真正回答您关于API调用位置的问题.您可以通过使用useEffect并传入一个空数组或对象作为第二个参数作为替代来进行API调用componentDidMount().这里的关键是第二个论点.如果不提供空数组或对象作为第二个参数,则将在每个渲染上调用API调用,并且它实际上变为a componentDidUpdate.
如文档中所述:
传入一个空数组[]输入告诉React你的效果不依赖于组件中的任何值,因此该效果只能在mount上运行并在unmount上清理; 它不会在更新时运行.
以下是您需要进行API调用的场景的一些示例:
尝试运行下面的代码并查看结果.
function User() {
const [firstName, setFirstName] = React.useState(null);
const [lastName, setLastName] = React.useState(null);
React.useEffect(() => {
fetch('https://randomuser.me/api/')
.then(results => results.json())
.then(data => {
const {name} = data.results[0];
setFirstName(name.first);
setLastName(name.last);
});
}, []); // <-- Have to pass in [] here!
return (
<div>
Name: {!firstName || !lastName ? 'Loading...' : `${firstName} ${lastName}`}
</div>
);
}
ReactDOM.render(<User />, document.querySelector('#app'));Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>Run Code Online (Sandbox Code Playgroud)
例如,如果您要显示每个页面具有userID状态/ prop的用户的配置文件页面,则应将该ID作为值传递到第二个参数中,useEffect以便为新用户ID重新获取数据.componentDidMount这里不够用,因为如果你直接从用户A转到用户B的个人资料,该组件可能不需要重新安装.
在传统的课程方式中,你会这样做:
componentDidMount() {
this.fetchData();
}
componentDidUpdate(prevProps, prevState) {
if (prevState.id !== this.state.id) {
this.fetchData();
}
}
Run Code Online (Sandbox Code Playgroud)
使用钩子,那将是:
useEffect(() => {
this.fetchData();
}, [id]);
Run Code Online (Sandbox Code Playgroud)
尝试运行下面的代码并查看结果.例如,将id更改为2以查看useEffect是否再次运行.
function Todo() {
const [todo, setTodo] = React.useState(null);
const [id, setId] = React.useState(1);
React.useEffect(() => {
if (id == null || id === '') {
return;
}
fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)
.then(results => results.json())
.then(data => {
setTodo(data);
});
}, [id]); // useEffect will trigger whenever id is different.
return (
<div>
<input value={id} onChange={e => setId(e.target.value)}/>
<br/>
<pre>{JSON.stringify(todo, null, 2)}</pre>
</div>
);
}
ReactDOM.render(<Todo />, document.querySelector('#app'));Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/react@16.8.1/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.8.1/umd/react-dom.development.js"></script>
<div id="app"></div>Run Code Online (Sandbox Code Playgroud)
你应该阅读,useEffect以便你知道你能做什么/不能做什么.
正如Dan Abramov在GitHub问题上所说:
从长远来看,我们会阻止这种(useEffect)模式,因为它会鼓励竞争条件.比如 - 你的通话开始和结束之间可能发生任何事情,你可能会得到新的道具.相反,我们会建议使用Suspense进行数据提取
所以请继续关注悬疑!
您可以使用为您提供钩子的库,例如https://resthooks.io
然后获取您的数据变得如此简单:
const article = useResource(ArticleResource.detail(), { id });
Run Code Online (Sandbox Code Playgroud)
现在您通过 id 抓取了文章。所有非快乐路径(加载、错误状态)分别由 Suspense 和Error 边界处理。
要开始遵循这个简单的指南:https : //resthooks.io/docs/getting-started/installation
压缩后只有 7kb,这将为您节省很多痛苦,并且从长远来看,由于重复代码较少,可以降低包的大小。
我只是将其发布为一种更简单的理解 acc 的方式。以我的努力。归功于 Yangshun Tay 的帖子,它几乎涵盖了所有内容。
代码:
useEffect(() => {
// here is where you make API call(s) or any side effects
fetchData('/data')
}, [] ) /** passing empty braces is necessary */
Run Code Online (Sandbox Code Playgroud)
因此,当组件创建(挂载)和销毁(卸载)时,使用useEffect(fn,[])空参数作为[]使fn()触发一次,而不依赖于任何值。
专家提示:
此外,如果您return()对此有所了解,fn那么它将componentWillUnmount()与类组件的生命周期相同。
useEffect(() => {
fetchData('/data')
return () => {
// this will be performed when component will unmount
resetData()
}
}, [] )
Run Code Online (Sandbox Code Playgroud)
如果您希望在某些值更改时调用 API,只需将该变量(存储值)传递到useEffect().
useEffect(() => {
// perform your API call here
updateDetails();
},[prop.name]) /** --> will be triggered whenever value of prop.name changes */
Run Code Online (Sandbox Code Playgroud)
这将确保每当值发生prop.name变化时,钩子中的函数都会被触发。
还要注意:这个钩子也将在安装组件时最初被调用。因此,那时您的 name 值可能处于初始状态,这在您看来是无意的。因此,您可以在函数中添加自定义条件以避免不必要的 API 调用。
| 归档时间: |
|
| 查看次数: |
11852 次 |
| 最近记录: |