简体   繁体   English

React useEffect 执行无限循环

[英]React useEffect does infinite loop

My useEffect is getting data from web api.我的 useEffect 正在从 web api 获取数据。 I want to render all posts on home page and trigger again my useEffect when someone create new post.我想在主页上呈现所有帖子,并在有人创建新帖子时再次触发我的 useEffect。 The problem is when I put dependancy on useEffect its start doing endless requests.问题是当我依赖 useEffect 它开始做无休止的请求时。 When I pass empty array as dependancy, when someone create new post it doesnt render on home page until I refresh the page.当我将空数组作为依赖项传递时,当有人创建新帖子时,它不会在主页上呈现,直到我刷新页面。 I read a lot in internet about that problem but still I dont know how to do it.我在互联网上阅读了很多关于这个问题的信息,但我仍然不知道该怎么做。 Thanks谢谢

function App() {
  const [posts, setPosts] = useState([]);

  useEffect(() => {
    const jwt = localStorage.getItem("jwt");

    fetch('https://localhost:44366/api/Posts/getAllPosts',
      {
        method: "GET",
        headers: {
          "Content-Type": "application/json",
          'Authorization': 'Bearer ' + jwt
        },
      })
      .then(r => r.json()).then(result => setPosts(result));
  }, [posts]);


  return (
    <div >
      <Router>
        <Header />
        <main className="App">
          {
            posts.map(post => (
              <Post keyToAppend={post.CreatedOn} username={post.User.FirstName} title={post.Title} content={post.Content} images={post.ImageUrls} avatarImage={post.User.MainImageUrl} />
            ))
          }
        </main>
      </Router>
      <Footer />
    </div>
  );
}

Post component:帖子组件:

const Post = ({ keyToAppend, username, title, content, images, avatarImage }) => {
    return (
        <div className="post" key={keyToAppend}>
            <div className="post__header">
                <Avatar
                    className="post__avatar"
                    alt="avatar"
                    src={avatarImage}
                />
                <h3 className="username">{username}</h3>

            </div>
            <h1 className="title">{title}</h1>
            <p className="content">{content}</p>
            <p>
                {typeof images != "undefined" ? <ImageSlider slides={images} /> : ""}
            </p>
        </div>
    )
}


export default Post;

Remove posts from the dependency array, so it's just [] .从依赖数组中删除posts ,所以它只是[] That will run the effect once, when the component loads.这将在组件加载时运行一次效果。

useEffect(() => {
  const jwt = localStorage.getItem("jwt");

  fetch('https://localhost:44366/api/Posts/getAllPosts',
    {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
        'Authorization': 'Bearer ' + jwt
      },
    })
    .then(r => r.json()).then(result => setPosts(result));
}, []);
// ^^−−−−− remove `posts` here

The reason it runs endlessly with your current code is that your effect callback changes the posts state member, which triggers the effect again (because posts is in the dependency array).它与您当前的代码无休止地运行的原因是您的效果回调更改了posts state 成员,这再次触发了效果(因为posts在依赖项数组中)。 You only need to include things in the dependency array that you read in the effect callback.您只需要在效果回调中读取的依赖数组中包含内容。 You never read posts in the effect callback.您从不阅读效果回调中的posts


Side note: That code is falling prey to the fetch API footgun I describe here .旁注:该代码正在成为我 在此处描述的fetch API footgun 的牺牲品。 You need to check r.ok before calling r.json (and handle errors):您需要在调用r.json r.ok并处理错误):

useEffect(() => {
    const jwt = localStorage.getItem("jwt");

    fetch("https://localhost:44366/api/Posts/getAllPosts", {
        method: "GET",
        headers: {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + jwt
        },
    })
    .then(r => {
        if (!r.ok) { // <=================
            throw new Error(`HTTP error ${r.status}`);
        }
        return r.json();
    })
    .then(result => setPosts(result))
    .catch(error => {
        // ...handle/report error here...
    });
}, []);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM