fix: suspense when key is falsy#357
Conversation
|
I think generally just |
|
@shuding I've made it simpler with |
| // update the state if the key changed (not the inital render) or cache updated | ||
| if ( | ||
| keyRef.current !== key || | ||
| (keyRef.current !== key && (!keyRef.current && !key)) || |
There was a problem hiding this comment.
I don’t know why the tests passed, but shouldn’t this be
(keyRef.current && key)?
However it still confuses me that when key is falsy, the effect will end early from line 361.
There was a problem hiding this comment.
good catch here. the previous test didn't really match the behavior so I removed it. I thought the condition was missed there but actually line 361 has already filtered it out.
| } | ||
|
|
||
| expect( | ||
| container.firstElementChild.lastElementChild.textContent |
There was a problem hiding this comment.
since <Suspense> might render inline styles onto children, then the html will look like
<div style="display: none !important">10</div>
<div>fallback</div>so I always queried the content of last element child here. it would be wether the fallback div or the children with returned data.
@shuding I'm not sure if it's sth I implemented incorrectly or there's any other elegant way to work around. other suspense test cases seem don't have this problem
|
I recently realized that this issue (#339) is more tricky than I thought, that: useSWR(null, { suspense: true })is an "anti-pattern". Theoretically, we should return empty data if However, that breaks the "rule" that SWR synchronously reads data with Suspense. That said, there's no easy way to avoid this: const [ready, setReady] = useState(false)
const { data } = useSWR(ready ? '/api' : null, { suspense: true }) // <- we can't throw promise here!
useEffect(() => { setReady(true) }, [])
console.log(data)We can't throw a promise on line 2, otherwise this component will never mount, and we will never reach line 4. And if we return empty data on line 2 if key is |
|
That makes sense. I think we should discourage that usage then? Maybe document how to lift the state up you may need? So you never pass null as key with suspense |
|
agree to leave it as current behavior. throwing promise truly breaks the how swr works. const useSuspensedSWR = (key, fetcher, options) => {
// ..customized logic, maybe handle arguments overloading
if (options && options.suspense && !key) {
throw new Promise(() => {})
}
// ..customized logic
useSwr(key, fetcher, options)
}this PR can be closed. or if there any other solution could be addressed I'd love to help and update PR. |
|
Then, what would be the recommended way of doing conditional and dependent fetching in Suspense ? Creating N nested Suspense contexts is not really what we would like I believe. #168 seems to help, but not sure what are the plans with it. |
Bugfix
When previous and current key are both not falsy while detecting the key change, schedule a rerender