【问题标题】:useEffect called in higher order componentuseEffect 在高阶组件中调用
【发布时间】:2020-03-08 23:58:27
【问题描述】:

更新后,React 不再使用高阶组件 (HOC) 中的 useEffect 钩子编译代码。我有一个 HOC,它连接到 Redux 存储并在需要时分派一个操作来获取数据。

import React, {useEffect} from 'react'
import PropTypes from 'prop-types' 
import { connect } from 'react-redux'

import SpinCenter from '../components/SpinCenter'
import { fetchObject } from '../actions/objects'
import { fetchIfNeeded } from '../utils'


const withObject = ({element}) => WrappedComponent => ({id, ...rest}) => {
  const hoc = ({status, object, fetchObject}) => {
    useEffect(() => {
      fetchIfNeeded(
        status,
        ()=>fetchObject(element, id),
      )
    })

    // Initial loading and error
    if (status === undefined || object === undefined) return <SpinCenter/>
    if (status.error) return <>error loading: {status.error.message}</>

    // Pass through the id for immediate access
    return <WrappedComponent {...{object, status, id}} {...rest} />
  }

  hoc.propTypes = {
    object: PropTypes.object,
    status: PropTypes.object,
    fetchObject: PropTypes.func.isRequired,
  }

  const mapStateToProps = state => ({
    object: state.data[element][id],
    status: state.objects[element][id]
  })

  const mapDispatchToProps = {
    fetchObject
  }

  const WithConnect = connect(mapStateToProps, mapDispatchToProps)(hoc)
  return <WithConnect/>
}

export default withObject

我希望这是有道理的。我想最好的方法是以某种方式将useEffect 放入一个功能组件中,但是这一切都应该发生的地方变得有点复杂。谁能帮我理解这个?

这是我遇到的错误。

React Hook "useEffect" is called in function "hoc" which is neither a React function component or a custom React Hook function

【问题讨论】:

    标签: reactjs redux higher-order-components


    【解决方案1】:

    您的组件名称需要以大写字符开头,这就是您遇到此问题的原因。您还可以优化连接和 hoc 代码以返回一个 hoc 实例,而不是一次又一次地这样做

    const withObject = ({element}) => WrappedComponent => {
      const Hoc = ({id, status, object, fetchObject,...rest}) => {
        useEffect(() => {
          fetchIfNeeded(
            status,
            ()=>fetchObject(element, id),
          )
        })
    
        // Initial loading and error
        if (status === undefined || object === undefined) return <SpinCenter/>
        if (status.error) return <>error loading: {status.error.message}</>
    
        // Pass through the id for immediate access
        return <WrappedComponent {...{object, status, id}} {...rest} />
      }
    
      Hoc.propTypes = {
        object: PropTypes.object,
        status: PropTypes.object,
        fetchObject: PropTypes.func.isRequired,
      }
    
      const mapStateToProps = state => ({
        object: state.data[element][id],
        status: state.objects[element][id]
      })
    
      const mapDispatchToProps = {
        fetchObject
      }
    
      return connect(mapStateToProps, mapDispatchToProps)(Hoc)
    }
    
    export default withObject
    

    【讨论】:

    • 天哪,原来如此。发现得好。从 React 的角度来看,这有点苛刻。
    • 是的,编译器很苛刻。另请查看更新的答案。从性能的角度来看,这可能会有所帮助
    • 您更新的答案也是我的第一种方法,但它返回一个对象而不是 React 组件,并在使用它时给我:Objects are not valid as a React child
    • 使用它时,您将创建一个类似const Wrap = withObject({})(WrappedComponent); 的组件,然后在您的React 组件中使用它,例如&lt;Wrap /&gt; 并不是说​​您不应该在组件内创建实例,而是在它之外创建实例跨度>
    • 我认为这正是我正在做的事情,但是在现有的代码库中事情变得有点难以改变。我将尝试在专用的代码盒中进行演示。到目前为止,谢谢。
    猜你喜欢
    • 2018-12-31
    • 1970-01-01
    • 2018-05-23
    • 2017-05-19
    • 2019-05-16
    • 2018-12-30
    • 2021-02-06
    • 1970-01-01
    • 2020-02-20
    相关资源
    最近更新 更多