Conditional render, why can't it be done?

I understand the reason this happens it that something doesn't understand that the Loader already checked if the prop is undefined, but typescript doesn't "pass the knowledge on". Whose fault is it? Is it a typescript problem or is it an eslint problem? Or both?
7 Replies
deforestor
deforestor13mo ago
And here's obviously the Loader checking, for context
Sybatron
Sybatron13mo ago
yeah but it's not getting the data that is Something[] the type in the place right now is Something[] | undefined and undefined doesn't have map method Loader can be fallback component of Suspense i think 🤔 if you remove props and leave just the styled loading or whatever you wrote there
King_codes
King_codes13mo ago
Actually quite an interesting question, but I guess even though Loader component checks if data exists before rendering the children, typescript is performing static type checking based on your code structure so it would not be able to infer the dynamic runtime behavior of your current code. So it is likely just considering the possibility that data might not be an array or undefined when it encounters profitabilities.map so it would raise an error based on assumption as well that profitabilities could be undefined or not an array. just my opinion
deforestor
deforestor13mo ago
Yeah it definitely is a static type checking problem, but in that case, this is kind of a bug in typescript's relationship with React then. I feel like the expected behavior should be that the object has already been clear of being undefined, just like a normal if(object)
Lautaro_dapin
Lautaro_dapin13mo ago
typescript wiith jsx is not smart enough what you could do is inside the Loader component instead of return children, force to be a function where you pass the data something like this
function Loader(props){
if (props.isLoading || !props.data) return <>Loading...</>

return children(props.data)
}

function Page(){
...
return(
<Loader isLoading={isLoading} data={data}>
{data=> (<>{JSON.stringify(data)}</>))
</Loader>
)
}
function Loader(props){
if (props.isLoading || !props.data) return <>Loading...</>

return children(props.data)
}

function Page(){
...
return(
<Loader isLoading={isLoading} data={data}>
{data=> (<>{JSON.stringify(data)}</>))
</Loader>
)
}
not tested but should work i think xD
deforestor
deforestor13mo ago
Yeah I changed the code to do that yesterday. But Suspense just works in a strange, but I guess, good way. Like, I expected Suspense to do kind of the same thing, render a Loading if it's not yet loaded, or the component when it is.. but what it did instead was to load every other component is already ready to render. This is a very good behavior, but at the same time, not the behavior I wanted for this page what is this witchcraft Ahhh ok, I get it now. The children is the function That is actually not a bad solution
Lautaro_dapin
Lautaro_dapin13mo ago
yep @deforestor then tell me if it works xD