基本上,我们componentDidMount()在React类组件的生命周期方法中进行API调用,如下所示
componentDidMount()
componentDidMount(){ //Here we do API call and do setState accordingly }
但是在React v16.7.0中引入了钩子之后,它几乎都像功能组件一样
我的查询是,我们到底需要在带有钩子的功能组件中进行API调用?
我们有什么类似的方法componentDidMount()吗?
是的,有一个类似(但不相同!)的componentDidMount钩子替代品,它就是useEffect钩子。
componentDidMount
useEffect
其他答案并不能真正回答您在哪里可以进行API调用的问题。您可以通过使用useEffect并将 空数组或对象作为第二个参数 来代替来进行API调用componentDidMount()。这里的关键是第二个参数。如果您不提供空数组或对象作为第二个参数,则将在每个渲染器上调用API调用,并且该调用实际上将变为componentDidUpdate。
componentDidUpdate
如文档中所述:
传递一个空的输入数组[]告诉React您的效果不依赖于组件中的任何值,因此该效果仅在安装时运行,而在卸载时清除;它不会在更新上运行。
以下是一些需要进行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')); <script src="https://unpkg.com/[email protected]/umd/react.development.js"></script> <script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script> <div id="app"></div>
例如,如果要显示用户的个人资料页面,其中每个页面都有一个userID状态/属性,则应将该ID作为值传递到的第二个参数中,useEffect以便为新的用户ID重新获取数据。componentDidMount这在这里是不够的,因为如果您直接从用户A转到用户B的配置文件,则可能不需要重新安装组件。
使用传统的类方法,您将执行以下操作:
componentDidMount() { this.fetchData(); } componentDidUpdate(prevProps, prevState) { if (prevState.id !== this.state.id) { this.fetchData(); } }
使用钩子,将是:
useEffect(() => { this.fetchData(); }, [id]);
尝试运行下面的代码,然后查看结果。例如,将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')); <script src="https://unpkg.com/[email protected]/umd/react.development.js"></script> <script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script> <div id="app"></div>
您应该继续阅读,以useEffect了解您可以/不能使用它。
正如Dan Abramov在此GitHub Issue上所说的那样:
从长远来看,我们将不鼓励这种(useEffect)模式,因为它会鼓励比赛条件。例如- 在通话开始和结束之间可能会发生任何事情,并且您可能会获得新的道具。相反,我们建议使用Suspense进行数据提取
因此,请继续关注悬念!