Skip to content

Instantly share code, notes, and snippets.

@diegoulloao
Last active February 7, 2020 07:09
Show Gist options
  • Save diegoulloao/06cdc4f21519bcd540d717a5070b3d3e to your computer and use it in GitHub Desktop.
Save diegoulloao/06cdc4f21519bcd540d717a5070b3d3e to your computer and use it in GitHub Desktop.
Photos component in React vs. Svelte
/**
*
* Photos React TSX Component
* @module ./components/Photos.tsx
*
*/
import React from 'react'
// UI:
import { Container, Button, Input, Typography, createMuiTheme }
from '@material-ui/core'
// Cards:
import { Card, CardActionArea, CardActions, CardContent, CardMedia }
from '@material-ui/core'
// Theme:
import { ThemeProvider } from '@material-ui/styles'
/**
*
* Material UI Theme
*
*/
const theme = createMuiTheme({
palette: {
type: 'dark'
}
})
/**
*
* DataType for Component State
*
*/
interface State {
photos: object[],
length: number
}
/**
*
* DataType for each Photo element (JSON)
*
*/
interface Photo {
id: string,
title: string,
thumbnailUrl: string,
url: string
}
export default
/**
*
* Photos Component
* @extends React.Component
*
*/
class Photos extends React.Component <any, State> {
public state = {
photos: [],
length: 5
}
/**
*
* Loads images from Server
* @return void
*
*/
private loadContent = async (): Promise <void> => {
let photos = await
fetch(`https://jsonplaceholder.typicode.com/photos?_limit=${this.state.length}`)
.then( response => response.json() )
;
this.setState({
photos
})
}
/**
*
* Resets image list when clicking button
* @return void
*
*/
private reset = (): void => {
this.setState({
photos: []
})
}
/**
*
* Change lenght value for loading
*
* @param { React.ChangeEvent } e
* @return void
*
*/
private lengthChange = ( e: React.ChangeEvent ): void => {
let target = e.target as HTMLInputElement
this.setState({
length: parseInt(target.value)
})
}
/**
*
* Render the application
* @return JSX.Element
*
*/
public render(): JSX.Element {
return(
<ThemeProvider theme={ theme }>
<Container maxWidth="lg">
<Typography variant="h2" style={ this.style }> Photos </Typography>
<div style={ this.style }>
<Input type="number" value={ this.state.length } onChange={ this.lengthChange } />
<Button variant="contained" color="secondary" onClick={ this.reset }> Reset </Button>
{ !this.state.photos.length && <Button variant="contained" color="primary" onClick={ this.loadContent }> Load </Button> }
</div>
<div>
{
this.state.photos.map( (photo: Photo) =>
<Card style={ this.cardStyle }>
<CardActionArea>
<CardMedia component="img" height="140" image={ photo.thumbnailUrl } />
<CardContent>
<Typography gutterBottom variant="h5" component="h2"> Image #{ photo.id } </Typography>
<Typography variant="body2" color="textSecondary" component="p"> { photo.title } </Typography>
</CardContent>
</CardActionArea>
<CardActions>
<Button size="small" href={ photo.url } target="_blank"> Open </Button>
</CardActions>
</Card>
)
}
</div>
</Container>
</ThemeProvider>
)
}
/**
*
* Component Styles
*
*/
private readonly style = {
marginBottom: '40px'
}
/**
*
* Cards Styles
*
*/
private readonly cardStyle = {
maxWidth: '345px',
marginBottom: '40px'
}
}
;
/**
*
* Photos React TSX Component
* @module ./components/Photos.tsx
*
*/
import React from 'react'
/**
*
* DataType for Component State
*
*/
interface State {
photos: object[],
length: number
}
/**
*
* DataType for each Photo element (JSON)
*
*/
interface Photo {
title: string,
thumbnailUrl: string
}
export default
/**
*
* Photos Component
* @extends React.Component
*
*/
class Photos extends React.Component <any, State> {
public state = {
photos: [],
length: 5
}
/**
*
* Loads images from Server
* @return void
*
*/
private loadContent = async (): Promise <void> => {
let photos = await
fetch(`https://jsonplaceholder.typicode.com/photos?_limit=${this.state.length}`)
.then( response => response.json() )
;
this.setState({
photos
})
}
/**
*
* Resets image list when clicking button
* @return void
*
*/
private reset = (): void => {
this.setState({
photos: []
})
}
/**
*
* Change lenght value for loading
*
* @param { React.ChangeEvent } e
* @return void
*
*/
private lengthChange = ( e: React.ChangeEvent ): void => {
let target = e.target as HTMLInputElement
this.setState({
length: parseInt(target.value)
})
}
/**
*
* Render the application
* @return JSX.Element
*
*/
public render(): JSX.Element {
return(
<React.Fragment>
<h1> Photos </h1>
<input type="number" value={ this.state.length } onChange={ this.lengthChange } />
<button onClick={ this.reset }> reset </button>
{ !this.state.photos.length && <button onClick={ this.loadContent }> load </button> }
<div>
{
this.state.photos.map( (photo: Photo) =>
<div style={ this.style }>
<img src={ photo.thumbnailUrl } alt="" /> <br />
<span> { photo.title } </span>
</div>
)
}
</div>
</React.Fragment>
)
}
/**
*
* Component Styles
*
*/
private readonly style = {
marginBottom: '40px'
}
}
;
/* Photos React TSX Component */
import React from 'react'
interface State {
photos: object[],
length: number
}
interface Photo {
title: string,
thumbnailUrl: string
}
export default
class Photos extends React.Component <any, State> {
public state = {
photos: [],
length: 5
}
private loadContent = async (): Promise <void> => {
let photos = await
fetch(`https://jsonplaceholder.typicode.com/photos?_limit=${this.state.length}`)
.then( response => response.json() )
;
this.setState({
photos
})
}
private reset = (): void => {
this.setState({
photos: []
})
}
private lengthChange = (e: React.ChangeEvent): void => {
let target = e.target as HTMLInputElement
this.setState({
length: parseInt(target.value)
})
}
public render(): JSX.Element {
return(
<React.Fragment>
<h1> Photos </h1>
<input type="number" value={ this.state.length } onChange={ this.lengthChange } />
<button onClick={ this.reset }> reset </button>
{ !this.state.photos.length && <button onClick={ this.loadContent }> load </button> }
<div>
{
this.state.photos.map( (photo: Photo) =>
<div style={ this.style }>
<img src={ photo.thumbnailUrl } alt="" /> <br />
<span> { photo.title } </span>
</div>
)
}
</div>
</React.Fragment>
)
}
private readonly style = {
marginBottom: '40px'
}
}
;
/* Photos React Component */
import React from 'react'
export default
class Photos extends React.Component {
state = {
photos: [],
length: 5
}
loadContent = async () => {
let response = await fetch(`https://jsonplaceholder.typicode.com/photos?_limit=${this.state.length}`)
let photos = await response.json()
this.setState({
photos
})
}
reset = () => {
this.setState({
photos: []
})
}
lengthChange = (e) => {
this.setState({
length: e.target.value
})
}
render() {
return(
<React.Fragment>
<h1> Photos </h1>
<input type="number" value={ this.state.length } onChange={ this.lengthChange } />
<button onClick={ this.reset }> reset </button>
{ !this.state.photos.length && <button onClick={ this.loadContent }> load </button> }
<div>
{
this.state.photos.map( photo =>
<div style={ this.style }>
<img src={ photo.thumbnailUrl } alt="" /> <br />
<tiny> { photo.title } </tiny>
</div>
)
}
</div>
</React.Fragment>
)
}
style = {
marginBottom: '40px'
}
}
;
<!-- PHOTOS Svelte Component -->
<script>
let photos = []
let length = 5
const loadContent = async () => {
let response = await fetch(`https://jsonplaceholder.typicode.com/photos?_limit=${length}`)
photos = await response.json()
}
const reset = () => {
photos = []
}
</script>
<main>
<h1> Photos </h1>
<input type="number" bind:value={ length } />
<button on:click={ reset }> reset </button>
{ #each photos as photo }
<div>
<img src={ photo.thumbnailUrl } alt="" /> <br />
<tiny> { photo.title } </tiny>
</div>
{ :else }
<button on:click={ loadContent }> load </button>
{ /each }
</main>
<style>
div { margin-bottom: 40px }
</style>
@diegoulloao
Copy link
Author

diegoulloao commented Feb 6, 2020

Se presenta mismo componente re-escrito en:

  • Svelte
  • React
  • React + Typescript
  • React + Typescript + JSDocs 3
  • React + Typescript + JSDocs 3 + Material UI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment