Skip to content

Instantly share code, notes, and snippets.

@usmanasif
Created March 31, 2021 19:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save usmanasif/eec3fa8e0f82ddcca707d72b3927442a to your computer and use it in GitHub Desktop.
Save usmanasif/eec3fa8e0f82ddcca707d72b3927442a to your computer and use it in GitHub Desktop.
/**
* ***************************SOLUTION***************************
* Following are the three core issues in the given code:
* 1) Fallback component missing. This is a mandatory prop plus the whole idea behind concurrent rendering is providing the smooth
* experience for instance saving user to see a blank screen while data is not ready. First of all the code given in the problem would not run
* but lets assume the code runs then the problem here is why are we using suspense if we are not showing a loading state.
*
* 2) Fetch on render technique is being used essentially making the suspense of no use. Data is fetched in useEffect and will be set in the state
* which at the end will render the data. This may lead to a problem called waterfall. Let's just say once user is loaded we have to render a component
* which will show the posts of the user. This will un-necessarily lead us to an un-intentional sequence which could have been parallelized.
*
* 3) In order to use the Suspense correctly we have to design it in a way where it can provide a mechanism for our fetchUserProfile function to communicate
* with react and tell that, data the component requires to load is not ready yet. But the given code doesn't certainly behaves in that scenario. Firstly it
* should fetch data in the user profile. Secondly it should not in use effect but using a global resource or so, thirdly api should throw a suspender while in pending state.
*
* ******************************* BELOW IS THE CODE THAT IMPLEMENTS THE SUSPENSE IN AN APPROPRIATE WAY*******************************
*/
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom'
// the mechanism which tells react data is not loaded yet---start
const fetchUserProfile = (userId) => {
let userPromise = getUserPromise(userId)
return {
user: wrappedFetchUserProfile(userPromise)
}
}
const getUserPromise = (userId) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
name: 'Foo'+userId,
email: 'Bar'
});
}, 3000);
})
}
const wrappedFetchUserProfile = (promise) => {
let status = "pending"
let result;
let suspender = promise.then(resp => {
status = "success"
result = resp
}).catch(error => {
status = "error"
result = error
})
return ({
read() {
switch(status) {
case 'pending':
throw suspender
case 'success':
return result
case 'error':
throw result
}
}
})
}
// the mechanism which tells react data is not loaded yet---end
const SuspensefulUserProfile = ({ resource, userId}) => {
return (
<Suspense fallback={<h1>Loading User {userId}</h1>}>
<UserProfile resource={resource} />
</Suspense>
);
};
const UserProfile = ({ resource }) => {
const data = resource.user.read()
return (
<>
<h1>{data.name}</h1>
<h2>{data.email}</h2>
</>
);
};
const UserProfileList = () => (
<>
<SuspensefulUserProfile userId={0} resource={fetchUserProfile(1)} />
<SuspensefulUserProfile userId={1} resource={fetchUserProfile(2)} />
<SuspensefulUserProfile userId={2} resource={fetchUserProfile(3)} />
</>
);
ReactDOM.render(
<React.StrictMode>
<UserProfileList />
</React.StrictMode>,
document.getElementById('root')
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment