基本上,我们在React类组件中的componentDidMount()个生命周期方法中进行API调用,如下所示

     componentDidMount(){
          //Here we do API call and do setState accordingly
     }

但是在React v16中引入挂钩之后.7.0,基本上都是功能组件

我的问题是,我们到底需要在哪里对带有钩子的功能组件进行API调用?

我们有没有类似于componentDidMount()的方法?

推荐答案

是的,有一个类似的(但不一样!)用钩子代替componentDidMount,这是useEffect钩子.

其他答案并不能真正回答您关于在哪里可以进行API调用的问题.您可以使用useEffectpassing in an empty array or object as the second argument代替componentDidMount()来进行API调用.这里的关键是第二个论点.如果不提供空数组或对象作为第二个参数,则会在每次渲染时调用API调用,它实际上会变成一个componentDidUpdate.

如文件所述:

传入输入的空数组[]告诉React,您的效果不依赖于组件中的任何值,因此效果将仅在装载时运行,在卸载时清除;它不会在更新时运行.

以下是一些需要进行API调用的场景示例:

API调用严格在Mount上进行

try 运行下面的代码并查看结果.

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/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>

每当某些属性/状态发生变化时调用API

例如,如果您正在显示一个用户的配置文件页面,其中每个页面都有一个userID state/prop,那么您应该将该ID作为一个值传递到第二个参数useEffect中,以便为新的用户ID重新提取数据.componentDidMount在这里是不够的,因为如果您直接从用户a转到用户B的配置文件,组件可能不需要重新安装.

按照传统的上课方式,你会做:

componentDidMount() {
  this.fetchData();
}

componentDidUpdate(prevProps, prevState) {
  if (prevState.id !== this.state.id) {
    this.fetchData();
  }
}

有了钩子,那就是:

useEffect(() => {
  this.fetchData();
}, [id]);

try 运行下面的代码并查看结果. Change the id to 2 for instance to see that useEffect is run again.

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/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>

你应该仔细阅读useEffect,以便知道你能/不能用它做什么.

担心

正如丹·阿布拉莫夫在this GitHub Issue年前所说:

从长远来看,我们将不鼓励这种(使用效应)模式,因为它鼓励比赛条件.比如——在通话开始和结束之间,任何事情都可能发生,你可能会得到新的props .相反,我们建议暂挂数据获取

所以请继续关注悬念!

Reactjs相关问答推荐

React中的useEffect钩子

我如何在不被 destruct 的情况下将导航栏固定在顶部?

在继承值更改时重置react 挂钩窗体字段值

MUI:在props 主题中找到的值:;错误;是[Object],而不是字符串或数字

useEffect不重新渲染

在reactjs中刷新页面时丢失状态值

React Context API 在 Next.js 中更改路由时获取默认数据

如何在Next.js应用程序中为路由[slug]生成.html文件?

使用 react pro 侧边栏展开折叠菜单

react 测试库不测试包含 react 路由 dom V6 的组件

如何保留我的下一个授权用户会话?所以我可以使用提供的 ID 在其他路由中获取数据

如何通过 React JS 中的映射将新元素添加到对象数据数组中

当用户输入相同信息时如何禁用更新

具有自动完成功能的 Formik material ui 无法按预期工作

React Router v6 - 访问嵌套路由和处理手写 url 的正确方法

未捕获的错误:操作必须是使用 redux/toolkit 的普通对象

无法重用我的组件,它只显示 1 次

当页面重新加载react 路由导航到第一页 v6

调用函数以获取数据并在数据到达时导航到链接

我想将悬停 colored颜色 更改为红色.写了一个话题,这个元素没有react ,怎么解决呢?