Reputation: 3080
After an update, React no longer compiles code with useEffect
hooks in Higher Order Components (HOC). I have a HOC that connects to the Redux store and dispatches an action to fetch data if needed.
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
I hope this makes sense. I guess the best approach would be to somehow place the useEffect
into a functional component, but it is getting a bit complicated where this all should happen. Can anyone help me make sense of this?
This is the error I am getting.
React Hook "useEffect" is called in function "hoc" which is neither a React function component or a custom React Hook function
Upvotes: 2
Views: 4317
Reputation: 281874
Your component name need to start with an upper case character which is why you get this issue. Also you can optimise the connect and hoc code to return an instance of hoc once instead of doing it again and again
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
Upvotes: 2