【问题标题】:React component rendered twice and useEffect not triggeredReact 组件渲染两次并且未触发 useEffect
【发布时间】:2020-12-12 11:12:07
【问题描述】:

我正在使用React + Gatsby,这是我的第一个React 项目。我在调用两次的组件时遇到了一些问题,而且我添加到该组件的 useEffect 钩子根本没有被触发。

到目前为止,我已经创建了一个名为CollectionsPage的页面:

import React from "react"
import { injectIntl } from "gatsby-plugin-intl"
import Layout from "../components/layout/layout"
import SEO from "../components/layout/seo"
import BGTState from "../context/bgt/bgtState"
import CollectionState from "../context/collection/collectionState"
import Collection from "../components/collection"

const CollectionsPage = ({ intl }) => {
  return (
    <BGTState>
      <Layout>
        <SEO
          lang={intl.locale}
          title={`${intl.formatMessage({ id: "collections" })}`}
        />
        {console.log("hey there")}
        <CollectionState>
          <Collection id={1} />
        </CollectionState>
      </Layout>
    </BGTState>
  )
}
export default injectIntl(CollectionsPage)

当我将站点浏览到http://localhost:3001/collections 时,我会在控制台中打印出来:

hey there
true
true

现在第一个日志hey there 来自CollectionsPage,而true 日志是从被调用两次的Collection 组件打印出来的。

这是我的Collection 组件

import React, { useContext, useEffect } from "react"
import CollectionContext from "../context/collection/collectionContext"
import { Link } from "gatsby"

const Collection = ({ id }) => {
  const collectionContext = useContext(CollectionContext)
  const { loading, collection, getCollection } = collectionContext

  console.log(true)

  useEffect(() => {
    getCollection(id)
  }, [])

  if (loading) return React.Fragment

  return (
    <div className="container">
      <div className="row">
        <img
          src={`${process.env.API_URL}${collection.feature_media.url}`}
          className="w-100 mt-2 mb-2"
          alt={""}
        />
        <Link to="#" className="bg-caption bg-no-underline">
          fall/winter 20/21
        </Link>
      </div>
    </div>
  )
}

export default Collection

现在这种行为似乎只发生在CollectionsPage,而不是Index 页面,这让我很困惑。这是Layout 组件,它包装了页面上的所有内容:

import React, { useContext, useEffect } from "react"
import PropTypes from "prop-types"
import { injectIntl } from "gatsby-plugin-intl"
import BGTContext from "../../context/bgt/bgtContext"
import { Spinner } from "react-bootstrap"
import Footer from "./footer"
import SearchState from "../../context/search/SearchState"
import Search from "../../components/search"

import NavbarMobile from "../../components/layout/navbarMobile"
import NavbarDesktop from "../../components/layout/navbarDesktop"

const Layout = ({ children, intl }) => {
  const bgtContext = useContext(BGTContext)
  const { loading, getSections, sections } = bgtContext

  useEffect(() => {
    getSections()
  }, [])

  return !loading ? (
    <>
      <NavbarMobile sections={sections} />
      <NavbarDesktop sections={sections} />
      <SearchState>
        <Search />
        <div className="container-fluid">
          <div className="main">
            {children}
            <Footer />
          </div>
        </div>
      </SearchState>
    </>
  ) : (
    <div className="container" style={{ height: "100vh" }}>
      <div className="row h-100 justify-content-center align-items-center">
        <Spinner animation="grow" />
      </div>
    </div>
  )
}

Layout.propTypes = {
  children: PropTypes.node.isRequired,
}

export default injectIntl(Layout)

正如您在此处看到的,我必须从 API 中获取这些部分,然后,我可以稍后渲染所有内容。也许是这种机制造成了问题?

事实上,在Collection 组件中我还有另一个钩子useEffect 调用getCollection,问题是这个钩子永远不会被触发,而且collection 是未定义的。

我能做些什么来解决这个问题?

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    首先,如果您希望您的 console.log 打印一次,然后在 useEffect(存在于 Collections 文件中)中打印您的 console.log。 如果您想查看您的 collection 值是否正在更改,请这样做:

    useEffect(()=>{
    console.log(collections);
    },[collections])
    

    每当您的收藏价值发生变化时,这个 useEffect 就会出现。

    【讨论】:

    • 如果我使用您的代码,则删除 useEffect 之外的 console.log 并将其添加到 useEffect 中不会打印任何内容。我得到cannot read url of undefined
    • 我要求你将console.log(true) 移到useEffect(() => { console.log(true) getSections() }, [])
    • 如果我在useEffect(() =&gt; { console.log(true) getSections() }, []) 中移动console.log(true) 只会打印一次
    • @sfarzoso 是的,这正是我要说的,如果你按照我说的方式进行操作,那么 true 将只打印一次,因为这意味着只有在第一次渲染时,console.log 才会进入图片或里面的任何东西useEffect(() =&gt; { // do whatever you want to }, [])
    猜你喜欢
    • 2022-11-26
    • 1970-01-01
    • 2021-10-31
    • 2020-08-16
    • 2019-05-26
    • 1970-01-01
    • 2017-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多