【问题标题】:Blank screen in reackhooks Home page with Maximum update depth exceeded. This can happen when a component calls setStatereackhooks 主页中的空白屏幕,超过了最大更新深度。这可能在组件调用 setState 时发生
【发布时间】:2021-01-29 21:17:19
【问题描述】:

我正在尝试向server.js 发送axios 获取请求,该请求向内容网站发送GET 请求。我在 Home.js 中没有得到任何数据,并且在控制台中出现以下错误。有人可以帮我在这里找出问题吗? 我可以在设置断点时看到setSearchResults中显示的数据,请参阅随附的屏幕截图。

警告:已超出最大更新深度。这可能发生在一个 组件在 useEffect 内部调用 setState,但 useEffect 要么 没有依赖数组,或者依赖项之一发生了变化 每次渲染。 在 Home(由 Context.Consumer 创建) 在路线中(在 App.js:18) 在 Switch 中(在 App.js:17) 在路由器中(由 BrowserRouter 创建) 在 BrowserRouter (在 App.js:15) 在应用程序中(在 src/index.js:11) 在路由器中(由 BrowserRouter 创建) 在 BrowserRouter 中(在 src/index.js:10)

Home.js

import React, { useRef, useState, useEffect, Component } from 'react';
import { usePosts } from "../custom-hooks/";
import Moment from 'moment';
import { Wave } from "react-animated-text";
import axios from "axios";

export default function Home() {

    const [posts, isLoading] = usePosts();
    const [searchTerm, setSearchTerm] = useState("");
    const [searchResults, setSearchResults] = useState([]);
    const [showColor, setShowColor] = useState("");
    const [findTag, setFindTag] = useState("");
    //const isMounted = useRef(false);

    /* In the Home tab, system displays all the published blogs from contentful website. 
       We can search for the blogs in the search area provided. Also on click on the tags should filter
       the blogs records.
    */

     
    const handleChange = (e) => {
        setSearchTerm(e.target.value);
    }

    
    useEffect(() => {
        const fetchData = async () => {
          try {
            const res = await axios.get('http://localhost:5000/service/blogpost');
            setSearchResults(res.data.items);
          } catch (e) {
            console.log(e);
          }
        }
        fetchData();
      }, []);

    useEffect(() => {
        const results = searchResults.filter(blog =>
            blog.fields.title.toLowerCase().includes(searchTerm) || blog.fields.title.toUpperCase().includes(searchTerm) || blog.fields.shortDescription.toLowerCase().includes(searchTerm)
            || blog.fields.shortDescription.toUpperCase().includes(searchTerm)
        );
        setSearchResults(results);
    }, [searchTerm, searchResults]);

    const getFilterTags = (event) => {
        const tagText = event.target.innerText;
        console.log("Print tag of a:"+tagText);
        const results = searchResults.filter(blog =>
            blog.fields.title.toLowerCase().includes(tagText) || blog.fields.title.toUpperCase().includes(tagText) 
        );
        setSearchResults(results);
    }


   
    const renderPosts = () => {
      if (isLoading) return(<div className="loadingIcon"> <p className="noSearchData">Loading...</p> </div>);

      return (
        <div className="wrap">
            <div className="row">
                <div className="column left" >
                    <h3>Search:</h3>
                    <label>
                        <div className="playerSearch_Home">
                            <div className="playerSearch_Icon">
                                <input type="text" className="playerSearch_Home_Input" placeholder="search posts..." value={searchTerm} onChange={handleChange} />
                            </div>
                            
                        </div>
                    </label>
                    <h3>Tags:</h3>
                    <label>
                        {
                            searchResults.map(({ fields: { id, tags } }) => (
                                <div key={id} className="techtags">
                                    {
                                         Array.isArray(tags) ? (
                                            tags.map((tag) => (
                                             <a onClick={getFilterTags} className="grouptechtags" style={{backgroundColor: `${showColor}`},{ marginRight: "10px" }} key={tag}>{tag}</a>
                                              ))
                                           ) : (
                                             <a onClick={getFilterTags} style={{backgroundColor: `${showColor}`}} className="grouptechtags">{tags}</a>
                                          )
                                    }
                                </div>
                            ))
                        }
                    </label>
                    <div className="twitterlink">
                        <a href="">Follow me on twitter</a>
                    </div>
                    <div className="reactStunning">
                    ????️ Built with react...!
                    </div>
                    <div>
                        <small className="copyright">© 2020 Soccerway</small>
                    </div>
                </div>
                <div className="column right" >
                    {!searchResults.length && (<div> <p className="noSearchData"><Wave text="No results available...!"/></p> </div>)}
                    <div className="container">
                        {
                            searchResults.map(({ sys: { id, createdAt}, fields: { title, image, shortDescription, description, tags, skillLevel, duration, slug } }) => (
                                <div key={id} className="column-center">
                                    <article key={id} className="blogmaintile">
                                        
                                        <div className="blogtitle">
                                            <span key={title}>{title}</span>
                                        </div>
                                        <section>
                                            <p className="blogdescription" key={shortDescription}>{shortDescription}</p>
                                            <span className="blogcreateddate" key={createdAt}>{Moment(createdAt).format('MMM DD YYYY')}</span>
                                            <span style={{display:"none"}} key={tags}>{tags}</span>
                                        </section>
                                        <section>
                                            <p className="bloglongdescription" key={description}>{description}</p>
                                        </section>
                                        <section className="col1">
                                            {
                                                <span className="difftags" key={skillLevel} >{skillLevel}</span>
                                            }
                                        </section>
                                        <span className="blogduration" key={duration} >{duration} min</span>
                                        <section className="col2">
                                            <a href={slug}>...more {'>'}{'>'}</a>
                                        </section>
                                    </article>
                                </div>
                            ))
                        }
                    </div>
                </div>
            </div>
        </div>
    )
  
      
    };
  
    return (
      <div className="posts__container">
        <div className="posts">{renderPosts()}</div>
      </div>
    );
  }

server.js

const express = require('express');
const bodyParser = require("body-parser");
const axios = require('axios');
const path = require('path');
const cors = require("cors");
const { get } = require('http');


const app = express()
const port = 5000
app.use(cors({
  origin: "http://localhost:3000"
}));

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.get('/service/blogpost', async(req, res) => {
  try {
    const blogposts = await axios({
     url: 'https://cdn.contentful.com/spaces/some_space_id/entries?access_token=some_token&limit=1000&skip=0',
     method:"GET"
    });
     res.status(200).send(blogposts.data);
  } catch (e) {
    res.status(500).json({ fail: e.message });
  }
})

app.listen(port, () => {
  console.log(`Listening at http://localhost:${port}`)
})

App.js

import React from 'react';
import { BrowserRouter, Route, Switch } from "react-router-dom";
import "./cssmodules/home.css";
import "./cssmodules/tutorialslist.css"
import "./cssmodules/singlepost.css";
import Home from "./components/Home";
import Tutorials from "./components/Tutorials";
import Navigation from './components/Navigation';
import TutorialsList from './components/TutorialsList';
import SinglePost from './components/SinglePost';


function App() {
  return (
    <BrowserRouter>
        <Navigation/>
          <Switch>
              <Route exact path="/" component={Home} />
              <Route path="/tutorials" component={Tutorials} />
              <Route path="/tutorialslist" component={TutorialsList} />
              <Route path="/:id" component={SinglePost} />
          </Switch>
    </BrowserRouter>
  );
};


export default App;

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import 'bootstrap/dist/css/bootstrap.css';

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById('root')
);

serviceWorker.unregister();

【问题讨论】:

    标签: reactjs express axios react-hooks


    【解决方案1】:

    我认为你的问题在那里:

    useEffect(() => {
      const results = searchResults.filter(blog =>
        blog.fields.title.toLowerCase().includes(searchTerm) || blog.fields.title.toUpperCase().includes(searchTerm) || blog.fields.shortDescription.toLowerCase().includes(searchTerm)
          || blog.fields.shortDescription.toUpperCase().includes(searchTerm)
        );
        setSearchResults(results);
    }, [searchTerm, searchResults]);
    

    方法filter返回一个新数组,你用setSearchResults()保存它,React调用重新渲染,这个useEffect检测到一个新的searchResults,运行它的回调......一次又一次。

    也许您需要在useMemo 计算过滤结果或从服务器接收后立即计算?

    向上

    可能是这样的:

      // Initiate a state for fetched posts.
      const [posts, setPosts] = useState([]);
    
      // Fetch data from server on mount.
      useEffect(() => {
        const fetchData = async () => {
          try {
            const { data: { items } } = await axios.get('http://localhost:5000/service/blogpost');
    
            setPosts(items);
          } catch (e) {
            console.log(e);
          }
        }
    
        fetchData();
      }, []);
    
      // Extract Tags from Posts with memoization.
      const tags = useMemo(() => {
        return posts.reduce((result, post) => {
          const { fields: { tags } } = post;
          const normalizedTags = Array.isArray(tags) ? tags : [tags];
    
          return [
            ...result,
            ...normalizedTags,
          ];
        }, []);
      }, [posts]);
    
      // Filter Posts with memoization.
      const filteredPosts = useMemo(() => {
        const term = searchTerm.toLowerCase();
    
        return posts.filter((post) => {
          const title = post.fields.title.toLowerCase();
          const description = post.shortDescription.title.toLowerCase();
    
          return [title, description].includes(term); // You can extend the condition with a check of selected tags here.
        });
      }, [posts, searchTerm]);
    
      // Render `tags` and `filteredPosts` in your template.
    

    对不起,如果我不明白你的任务

    【讨论】:

    • 我已经通过以下方式使用了useMemo(),但是现在我的搜索不起作用const results = React.useMemo( () =&gt; searchResults.filter((blog) =&gt; { blog.fields.title.toLowerCase().includes(searchTerm) || blog.fields.title.toUpperCase().includes(searchTerm) || blog.fields.shortDescription.toLowerCase().includes(searchTerm) || blog.fields.shortDescription.toUpperCase().includes(searchTerm) }), [searchTerm, searchResults] );
    • 在与 server.js 集成之前的原始工作
    • 是否需要同时通过输入文本和选定标签过滤帖子?
    • 我今天晚上会尝试并会回复
    • 现在一切都好,我赞成并接受了您的回答。我没有正确看到你的代码。
    猜你喜欢
    • 2021-04-29
    • 2020-12-11
    • 2019-08-12
    • 1970-01-01
    • 2019-07-25
    • 2020-10-22
    • 2023-04-09
    • 1970-01-01
    • 2018-09-13
    相关资源
    最近更新 更多