Skip to content

Instantly share code, notes, and snippets.

@drodsou
Created March 28, 2022 01:59
Show Gist options
  • Save drodsou/2bbc7c73fdf96c16cb7c135fb6df63e3 to your computer and use it in GitHub Desktop.
Save drodsou/2bbc7c73fdf96c16cb7c135fb6df63e3 to your computer and use it in GitHub Desktop.
Fetch cascade example in React
/*
Example of async fetch of Authors, and clicking on an author, new async fetch of selected author Posts
Try it in your machine:
- npm create vite@latest example1 -- --template react && cd example1 && npm install
- paste code bellow in src/App.jsx
*/
import React from 'react';
// -- helpers
function wait(ms=500) {
return new Promise(resolve=>{setTimeout(resolve,ms)});
}
const db = {
author : [
{author: 'a1'},
{author: 'a2'},
],
post : [
{post: 'p-a1-1', author: 'a1'},
{post: 'p-a1-2', author: 'a1'},
{post: 'p-a2-1', author: 'a2'},
],
}
globalThis.data = {} // debug
// -- cascading db fetch
export default class Cascade extends React.Component {
/*
-- final data structure.
-- Hierarchical data allows to not need hierarchical view components
data: {
author: {
state: wait,error,ok,
rows: arr,
post: {
state: wait,error,ok,
rows: arr,
}
}
*/
// -- using sync 'state'
data = globalThis.data // debug
up = ()=>this.forceUpdate();
//-- simulates authors fetch
async getAuthorAll() {
const {data, up} = this;
up(data.author = {state:'wait'})
await wait()
data.author = {state : 'ok', rows : [...db.author]};
up();
}
//-- simulates posts fetch
async getPostAuthor(author) {
const {data, up} = this;
up(data.author.post = {state:'wait'})
await wait()
if (Math.random()<0.5) { // chance of error
data.author.post = { state: 'error' }
} else {
data.author.post = {
state:'ok',
rows: [...(db.post.filter(e=>e.author === author)) ]
};
}
up();
}
// -- start
componentDidMount() {
this.getAuthorAll();
}
// -- view
render() {
const {data, up} = this;
return <>
<h1>Author</h1>
{data.author?.state==='wait' && 'loading author'}
{data.author?.state==='error' && 'error loading author'}
{data.author?.state==='ok' &&
<ul>
{data.author.rows.map(e=>(
<li key={e.author}
onClick={ (e)=>{this.getPostAuthor(e.target.innerText)}
}>
{e.author}
</li>
))}
</ul>
}
{data.author?.post && <h1>Post</h1>}
{data.author?.post?.state==='wait' && 'loading posts'}
{data.author?.post?.state==='error' && 'error loading posts'}
{data.author?.post?.state==='ok' &&
<ul>
{data.author.post.rows.map(e=>(
<li key={e.post}
onClick={ (e)=>{console.log('post',e.target.innerText)}
}>
{e.post}
</li>
))}
</ul>
}
<style dangerouslySetInnerHTML={{__html:`
body { font-size: 20px; font-family: sans-serif; }
li { cursor:pointer; margin-bottom:10px;}
`}}/>
</>;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment