I'm trying to get more fortable with using higher order ponents so I'm working on refactoring an application. I have four different ponents that all reuse the same fetchData
request, as well as error/loading conditionals. My plan is to take this reusable data and put it into a HOC. I've tried many different examples from StackOverflow, Reddit, Github, etc and none of them are working in my specific case.
Here's my HOC:
const WithDataRendering = WrappedComponent => props => {
class WithDataRenderingComponent extends Component {
ponentDidMount() {
this.props.fetchData(url)
}
render() {
if (this.props.hasErrored) {
return (
<p>
Sorry! There was an error loading the items:{" "}
{this.props.hasErrored.message}
</p>
)
}
if (this.props.isLoading) {
return (
<div>
<Skeleton count={10} />
</div>
)
}
return <WrappedComponent {...this.props} />
}
}
const mapStateToProps = state => {
return {
data: state.data,
hasErrored: state.dataHasErrored,
isLoading: state.dataIsLoading
}
}
const mapDispatchToProps = dispatch => {
return {
fetchData: url => dispatch(fetchData(url))
}
}
return connect(mapStateToProps, mapDispatchToProps)(
WithDataRenderingComponent
)
}
export default WithDataRendering
And here's a ponent that I'm trying to wrap with the HOC:
export class AllData extends Component<Props> {
render() {
return (
...
)
}
}
const mapStateToProps = state => {
return {
data: state.data,
hasErrored: state.dataHasErrored,
isLoading: state.dataIsLoading
}
}
const mapDispatchToProps = dispatch => {
return {
fetchData: url => dispatch(fetchData(url))
}
}
export default pose(
connect(mapStateToProps, mapDispatchToProps),
WithDataRendering(AllData)
)
I get three errors in the console:
Warning: Component(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.
invariant.js:42 Uncaught Error: Component(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.
ReactDOMComponentTree.js:111 Uncaught TypeError: Cannot read property '__reactInternalInstance$24sdkzrlvvz' of null
A couple other techniques I tried are in this SO post and this gist. I've tried using pose
and not using it, doesn't matter. I'm really at a loss here. Any ideas why this HOC isn't rendering properly?
Also, I'm not opposed to using render props
as a solution if that fits better. I need to get more practice with both methods.
I'm trying to get more fortable with using higher order ponents so I'm working on refactoring an application. I have four different ponents that all reuse the same fetchData
request, as well as error/loading conditionals. My plan is to take this reusable data and put it into a HOC. I've tried many different examples from StackOverflow, Reddit, Github, etc and none of them are working in my specific case.
Here's my HOC:
const WithDataRendering = WrappedComponent => props => {
class WithDataRenderingComponent extends Component {
ponentDidMount() {
this.props.fetchData(url)
}
render() {
if (this.props.hasErrored) {
return (
<p>
Sorry! There was an error loading the items:{" "}
{this.props.hasErrored.message}
</p>
)
}
if (this.props.isLoading) {
return (
<div>
<Skeleton count={10} />
</div>
)
}
return <WrappedComponent {...this.props} />
}
}
const mapStateToProps = state => {
return {
data: state.data,
hasErrored: state.dataHasErrored,
isLoading: state.dataIsLoading
}
}
const mapDispatchToProps = dispatch => {
return {
fetchData: url => dispatch(fetchData(url))
}
}
return connect(mapStateToProps, mapDispatchToProps)(
WithDataRenderingComponent
)
}
export default WithDataRendering
And here's a ponent that I'm trying to wrap with the HOC:
export class AllData extends Component<Props> {
render() {
return (
...
)
}
}
const mapStateToProps = state => {
return {
data: state.data,
hasErrored: state.dataHasErrored,
isLoading: state.dataIsLoading
}
}
const mapDispatchToProps = dispatch => {
return {
fetchData: url => dispatch(fetchData(url))
}
}
export default pose(
connect(mapStateToProps, mapDispatchToProps),
WithDataRendering(AllData)
)
I get three errors in the console:
Warning: Component(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.
invariant.js:42 Uncaught Error: Component(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.
ReactDOMComponentTree.js:111 Uncaught TypeError: Cannot read property '__reactInternalInstance$24sdkzrlvvz' of null
A couple other techniques I tried are in this SO post and this gist. I've tried using pose
and not using it, doesn't matter. I'm really at a loss here. Any ideas why this HOC isn't rendering properly?
Also, I'm not opposed to using render props
as a solution if that fits better. I need to get more practice with both methods.
-
First thing I notice is that your HOC exports
WithGoDataRendering
which isn't defined anywhere (did you meanWithDataRendering
?) – hbauer Commented Apr 4, 2018 at 22:01 - Sorry, that was a typo while I was modifying my code. I've corrected it to reflect the proper names – wildlifehexagon Commented Apr 4, 2018 at 22:03
-
You'll want to drop the
props =>
argument toWithDataRendering
, and you currentlyconnect
both in the HOC and in thepose
application (although that probably won't cause any errors). Just briefly glanced over the code though, so there might be some other issues. – Oblosys Commented Apr 5, 2018 at 0:04 -
You're right,
props =>
was the main issue. Will post more details later. Thank you. – wildlifehexagon Commented Apr 5, 2018 at 21:22 -
Apologies for the off-topic question but what does this mean:
export class AllData extends Component<Props> {
? I am referring to the '<Props> alongsideComponent
syntax. – Kayote Commented Jul 23, 2018 at 15:13
1 Answer
Reset to default 6I was able to fix this by dropping the props =>
argument as Oblosys suggested. I also reconfigured the export
statement in AllData to be:
export default connect(mapStateToProps, mapDispatchToProps)(WithDataRendering(AllData))
since I didn't really need to use pose
there.