I'm using swr in a react project and I'm trying to generify the loading/error messages in a parent component wrapping the components loading data.
The wrapping component is a very simple component returning different messages depending on the loadingstate.
const LoadingView = ({ loading, error, children }) => {
if (error) {
return <span>Error</span>
}
if (loading) {
return <span>Loading...</span>
}
return <Container>{children}</Container>
}
And the child component:
const WipePeriodTeams = ({ wipePeriodId }) => {
const params = useParams()
const { data, error } = useSWR(
`/some-endpoint`
)
return <LoadingView loading={!data}>{console.log(data.length)}</LoadingView> <--- ReferenceError
}
The issue being that the child component's render method is always evaluated, doesn't matter if loading is true/false which could end up in a ReferenceError due to data not loaded.
Is the return value always evaluated no matter what the parent returns? Is there a way around this?
Thanks! :)
That is the correct behaviour - the evaluation of children occurs in the parent component. You are seeing an error because data is undefined, so data.length is trying to point to a property of something that doesn't exist.
One way to avoid the error is to use && separator to check if data exists before referring to its length:
<LoadingView loading={!data}>{data && console.log(data.length)}</LoadingView>
Another approach is to replace your JSX expression with a component. I understand your example has a contrived child console.log(), but in the real world you're likely to pass in another component(s). Components are functions, so not evaluated at parent level:
const ChildComponent = ({data}) => {
return (<>{console.log(data.length)}</>)
}
const Parent = () => {
const { data, error } = useSWR(
`/some-endpoint`
);
return (
<LoadingView loading={!data}>
<ChildComponent data={data} />
</LoadingView>
);
}
There'a a few other approaches to delaying evaluation of children if you dig around online, but be cautious as some of them feel like messy workarounds.