Skip to content

Instantly share code, notes, and snippets.

@bazen-teklehaymanot
Created April 29, 2021 18:12
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 bazen-teklehaymanot/38e29b3dd4b9d08a02c2f0cbf7b0aedd to your computer and use it in GitHub Desktop.
Save bazen-teklehaymanot/38e29b3dd4b9d08a02c2f0cbf7b0aedd to your computer and use it in GitHub Desktop.
Conditional rendering in react
import ReactDOM from 'react-dom';
import React, { Fragment, FC, useState, useEffect } from 'react';
import reportWebVitals from './reportWebVitals';
export enum StateTypes{
Init='INIT',
Error='ERROR',
Success='SUCCESS',
Processing='PROCESSING',
}
export function useAsync<TPayload>(asyncTask:Function):StateMachine<TPayload> {
const [ state, setState ] = useState<StateMachine<TPayload>>({ currentState:StateTypes.Init});
useEffect(()=>{ runAsyncTasks(); },[]);
async function runAsyncTasks(){
try{
setState({ currentState:StateTypes.Processing,message:'Loading...'})
const result = await asyncTask();
setState({ currentState:StateTypes.Success,message:'Success',payload:result})
}catch(error){
setState({currentState:StateTypes.Error,error, message: error.message})
}
}
return state;
}
export interface StateMachine<T>{
currentState: StateTypes
payload?: T
error?:Error
message?: string
}
interface StateMachineWrapperProps{
asyncTask: Function
component: React.ComponentType<any>
}
interface ConditionalRendererProps{
activeState: string
mapping: { [key: string]:React.ReactNode}
}
export const ConditionalRenderer:FC<ConditionalRendererProps>=(props)=>{
return(
<Fragment>
{ props.mapping[props.activeState] }
</Fragment>
)
}
export const StateMachineWrapper:FC<StateMachineWrapperProps> =(props) =>{
const machine = useAsync<string>(props.asyncTask)
return (
<ConditionalRenderer
activeState={machine.currentState}
mapping={{
[StateTypes.Init]:<Fragment/>,
[StateTypes.Processing]: <p>{machine.message}</p>,
[StateTypes.Error]: <p>{machine.message}</p>,
[StateTypes.Success]: <props.component {...machine.payload}/>
}}
/>
)
}
function longRunningTask(){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve({data: 'Async task completed'})
},1000)
});
}
interface ContentProps{
data: string
}
export const Content:FC<ContentProps>=(props)=>{
return (
<div>
<h3>Content</h3>
<p>{ props.data }</p>
</div>
)
}
export const ContentWrapper:FC =()=>{
return (
<StateMachineWrapper
asyncTask={longRunningTask}
component={Content}/>
)
}
ReactDOM.render(
<React.StrictMode>
<ContentWrapper />
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment